# core/parsers/invariant.parser.ts

> 37 lines of code and 11 definitions.

Tree: GovLab Context
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/context#file-context-core-parsers-invariant-parser-ts
Source text: https://banes-lab.com/source/context/core/parsers/invariant.parser.ts.txt

Listed in [core/parsers](https://banes-lab.com/api/source/context/core/parsers.md), after [core/parsers/document.parser.ts](https://banes-lab.com/source/context/core/parsers/document.parser.ts.md) and before [core/parsers/metadata.parser.ts](https://banes-lab.com/source/context/core/parsers/metadata.parser.ts.md).

## Definitions

- `clauseOf` (lexical_declaration, line 12)
- `parseInvariant` (lexical_declaration, line 29, exported)
- `propertyOf` (lexical_declaration, line 24)
- `CLAUSE_MARKERS` (lexical_declaration, line 9)
- `NAME_END` (lexical_declaration, line 10)
- `at` (lexical_declaration, line 13)
- `start` (lexical_declaration, line 17)
- `ends` (lexical_declaration, line 25)
- `body` (lexical_declaration, line 30, exported)
- `colon` (lexical_declaration, line 31, exported)
- `afterName` (lexical_declaration, line 32, exported)

## Contained in

- [core/parsers](https://banes-lab.com/anatomy/context/folder-context-core-parsers.md)

## Used by

- [core/parsers/document.parser.ts](https://banes-lab.com/source/context/core/parsers/document.parser.ts.md)

## Linked from

- [core/parsers](https://banes-lab.com/anatomy/context/folder-context-core-parsers.md)

## Source

```typescript
import {
    INVARIANT_OBJECTOR,
    INVARIANT_PARTIES,
    INVARIANT_PREFIX,
    INVARIANT_SET,
} from "#configuration/constants/grammar.constants";
import type { PagInvariant } from "#types/grammar.document.types";

const CLAUSE_MARKERS = [INVARIANT_SET, INVARIANT_PARTIES, INVARIANT_OBJECTOR];
const NAME_END = ":";

const clauseOf = function clauseOf(text: string, marker: string): string | null {
    const at = text.indexOf(marker);
    if (at === -1) {
        return null;
    }
    const start = at + marker.length;
    const ends = CLAUSE_MARKERS.map((other) => (other === marker ? -1 : text.indexOf(other, start))).filter(
        (index) => index !== -1,
    );
    return text.slice(start, ends.length === 0 ? text.length : Math.min(...ends)).trim();
};

const propertyOf = function propertyOf(afterName: string): string {
    const ends = CLAUSE_MARKERS.map((marker) => afterName.indexOf(marker)).filter((index) => index !== -1);
    return (ends.length === 0 ? afterName : afterName.slice(0, Math.min(...ends))).trim();
};

export const parseInvariant = function parseInvariant(text: string, line: number): PagInvariant {
    const body = text.slice(INVARIANT_PREFIX.length);
    const colon = body.indexOf(NAME_END);
    const afterName = colon === -1 ? "" : body.slice(colon + 1);
    return {
        line,
        name: (colon === -1 ? body : body.slice(0, colon)).trim(),
        objector: clauseOf(afterName, INVARIANT_OBJECTOR),
        parties: clauseOf(afterName, INVARIANT_PARTIES),
        property: propertyOf(afterName),
        set: clauseOf(afterName, INVARIANT_SET),
    };
};
```
