Browse Source

Update parse

Put common English parse functions to en/common.
master
TheoryOfNekomata 7 months ago
parent
commit
c5a65ae9d8
3 changed files with 132 additions and 227 deletions
  1. +6
    -113
      packages/core/src/systems/en-UK/long-count/parse.ts
  2. +6
    -113
      packages/core/src/systems/en-US/short-count/parse.ts
  3. +120
    -1
      packages/core/src/systems/en/common.ts

+ 6
- 113
packages/core/src/systems/en-UK/long-count/parse.ts View File

@@ -30,6 +30,12 @@ import {
TENS_ONES_SEPARATOR,
TensName,
THOUSAND,
DoParseState,
ParseGroupsMode,
ParserState,
parseOnes,
parseTenPlusOnes,
parseTens,
} from '../../en/common';

const FINAL_TOKEN = '' as const;
@@ -61,13 +67,6 @@ export const tokenize = (value: string) => (
.filter((maybeToken) => maybeToken.length > 0)
);

interface DoParseState {
groupNameCurrent: string;
millias: number[];
milliaIndex: number;
done: boolean;
}

/**
* Deconstructs a group name token (e.g. "million", "duodecillion", etc.) to its affixes and
* parses them.
@@ -219,50 +218,6 @@ const getGroupPlaceFromGroupName = (groupName: string) => {
return bigGroupPlace * BigInt(2) + (groupName.startsWith(THOUSAND) ? BigInt(1) : BigInt(0));
};

/**
* Mode of the group parser.
*/
enum ParseGroupsMode {
/**
* Initial mode.
*/
INITIAL = 'initial',
/**
* Has parsed a ones name.
*/
ONES_MODE = 'ones',
/**
* Has parsed a tens name.
*/
TENS_MODE = 'tens',
/**
* Has parsed a ten-plus-ones name.
*/
TEN_PLUS_ONES_MODE = 'tenPlusOnes',
/**
* Has parsed a "hundred" token.
*/
HUNDRED_MODE = 'hundred',
/**
* Has parsed a "thousand" or any "-illion" token.
*/
THOUSAND_MODE = 'thousand',
/**
* Done parsing.
*/
DONE = 'done',
}

/**
* State of the group parser.
*/
interface ParserState {
lastToken?: string;
groups: Group[];
mode: ParseGroupsMode;
negative: boolean;
}

const parseThousand = (acc: ParserState, token: string): ParserState => {
const lastGroup = acc.groups.at(-1) ?? [...EMPTY_PLACE];

@@ -337,68 +292,6 @@ const parseFinal = (acc: ParserState): ParserState => {
return acc;
};

const parseOnes = (acc: ParserState, token: string): ParserState => {
if (acc.mode === ParseGroupsMode.THOUSAND_MODE) {
// Create next empty place
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.ONES_MODE,
groups: [...acc.groups, [...EMPTY_PLACE]],
};
}
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.ONES_MODE,
};
};

const parseTenPlusOnes = (acc: ParserState, token: string): ParserState => {
const tenPlusOnes = TEN_PLUS_ONES.findIndex((t) => t === token);
const lastGroup = acc.groups.at(-1) ?? [...EMPTY_PLACE];
if (acc.mode === ParseGroupsMode.THOUSAND_MODE) {
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TEN_PLUS_ONES_MODE,
groups: [...acc.groups, [`01${tenPlusOnes}` as GroupDigits, lastGroup[GROUP_PLACE_INDEX] - BigInt(1)]],
};
}

lastGroup[GROUP_DIGITS_INDEX] = `${lastGroup[GROUP_DIGITS_INDEX].slice(0, 1)}1${tenPlusOnes}` as GroupDigits;
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TEN_PLUS_ONES_MODE,
groups: [...acc.groups.slice(0, -1), lastGroup],
};
};

const parseTens = (acc: ParserState, token: string): ParserState => {
const tens = TENS.findIndex((t) => t === token);
const lastGroup = acc.groups.at(-1) ?? [...EMPTY_PLACE];
if (acc.mode === ParseGroupsMode.THOUSAND_MODE) {
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TENS_MODE,
groups: [...acc.groups, [`0${tens}0` as GroupDigits, lastGroup[GROUP_PLACE_INDEX] - BigInt(1)]],
};
}

lastGroup[GROUP_DIGITS_INDEX] = (
`${lastGroup[GROUP_DIGITS_INDEX].slice(0, 1)}${tens}${lastGroup[GROUP_DIGITS_INDEX].slice(2)}`
) as GroupDigits;

return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TENS_MODE,
groups: [...acc.groups.slice(0, -1), lastGroup],
};
};

/**
* Parses groups from a string.
* @param tokens - The string to parse groups from.


+ 6
- 113
packages/core/src/systems/en-US/short-count/parse.ts View File

@@ -30,6 +30,12 @@ import {
TENS_ONES_SEPARATOR,
TensName,
THOUSAND,
DoParseState,
ParseGroupsMode,
ParserState,
parseOnes,
parseTens,
parseTenPlusOnes,
} from '../../en/common';

const FINAL_TOKEN = '' as const;
@@ -55,13 +61,6 @@ export const tokenize = (value: string) => (
.filter((maybeToken) => maybeToken.length > 0)
);

interface DoParseState {
groupNameCurrent: string;
millias: number[];
milliaIndex: number;
done: boolean;
}

/**
* Deconstructs a group name token (e.g. "million", "duodecillion", etc.) to its affixes and
* parses them.
@@ -217,50 +216,6 @@ const getGroupPlaceFromGroupName = (groupName: string) => {
return bigGroupPlace + BigInt(1);
};

/**
* Mode of the group parser.
*/
enum ParseGroupsMode {
/**
* Initial mode.
*/
INITIAL = 'initial',
/**
* Has parsed a ones name.
*/
ONES_MODE = 'ones',
/**
* Has parsed a tens name.
*/
TENS_MODE = 'tens',
/**
* Has parsed a ten-plus-ones name.
*/
TEN_PLUS_ONES_MODE = 'tenPlusOnes',
/**
* Has parsed a "hundred" token.
*/
HUNDRED_MODE = 'hundred',
/**
* Has parsed a "thousand" or any "-illion" token.
*/
THOUSAND_MODE = 'thousand',
/**
* Done parsing.
*/
DONE = 'done',
}

/**
* State of the group parser.
*/
interface ParserState {
lastToken?: string;
groups: Group[];
mode: ParseGroupsMode;
negative: boolean;
}

const parseThousand = (acc: ParserState, token: string): ParserState => {
const lastGroup = acc.groups.at(-1) ?? [...EMPTY_PLACE];

@@ -335,68 +290,6 @@ const parseFinal = (acc: ParserState): ParserState => {
return acc;
};

const parseOnes = (acc: ParserState, token: string): ParserState => {
if (acc.mode === ParseGroupsMode.THOUSAND_MODE) {
// Create next empty place
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.ONES_MODE,
groups: [...acc.groups, [...EMPTY_PLACE]],
};
}
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.ONES_MODE,
};
};

const parseTenPlusOnes = (acc: ParserState, token: string): ParserState => {
const tenPlusOnes = TEN_PLUS_ONES.findIndex((t) => t === token);
const lastGroup = acc.groups.at(-1) ?? [...EMPTY_PLACE];
if (acc.mode === ParseGroupsMode.THOUSAND_MODE) {
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TEN_PLUS_ONES_MODE,
groups: [...acc.groups, [`01${tenPlusOnes}` as GroupDigits, lastGroup[GROUP_PLACE_INDEX] - BigInt(1)]],
};
}

lastGroup[GROUP_DIGITS_INDEX] = `${lastGroup[GROUP_DIGITS_INDEX].slice(0, 1)}1${tenPlusOnes}` as GroupDigits;
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TEN_PLUS_ONES_MODE,
groups: [...acc.groups.slice(0, -1), lastGroup],
};
};

const parseTens = (acc: ParserState, token: string): ParserState => {
const tens = TENS.findIndex((t) => t === token);
const lastGroup = acc.groups.at(-1) ?? [...EMPTY_PLACE];
if (acc.mode === ParseGroupsMode.THOUSAND_MODE) {
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TENS_MODE,
groups: [...acc.groups, [`0${tens}0` as GroupDigits, lastGroup[GROUP_PLACE_INDEX] - BigInt(1)]],
};
}

lastGroup[GROUP_DIGITS_INDEX] = (
`${lastGroup[GROUP_DIGITS_INDEX].slice(0, 1)}${tens}${lastGroup[GROUP_DIGITS_INDEX].slice(2)}`
) as GroupDigits;

return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TENS_MODE,
groups: [...acc.groups.slice(0, -1), lastGroup],
};
};

/**
* Parses groups from a string.
* @param tokens - The string to parse groups from.


+ 120
- 1
packages/core/src/systems/en/common.ts View File

@@ -1,4 +1,10 @@
import { Group, GroupPlace } from '../../common';
import {
Group,
GROUP_DIGITS_INDEX,
GROUP_PLACE_INDEX,
GroupDigits,
GroupPlace,
} from '../../common';

export const GROUP_SEPARATOR = ' ' as const;

@@ -341,3 +347,116 @@ export const makeNegative = (s: string) => {
const negativePrefix = `${NEGATIVE} `;
return s.startsWith(negativePrefix) ? s.slice(negativePrefix.length) : `${negativePrefix}${s}`;
};

export interface DoParseState {
groupNameCurrent: string;
millias: number[];
milliaIndex: number;
done: boolean;
}

/**
* Mode of the group parser.
*/
export enum ParseGroupsMode {
/**
* Initial mode.
*/
INITIAL = 'initial',
/**
* Has parsed a ones name.
*/
ONES_MODE = 'ones',
/**
* Has parsed a tens name.
*/
TENS_MODE = 'tens',
/**
* Has parsed a ten-plus-ones name.
*/
TEN_PLUS_ONES_MODE = 'tenPlusOnes',
/**
* Has parsed a "hundred" token.
*/
HUNDRED_MODE = 'hundred',
/**
* Has parsed a "thousand" or any "-illion" token.
*/
THOUSAND_MODE = 'thousand',
/**
* Done parsing.
*/
DONE = 'done',
}

/**
* State of the group parser.
*/
export interface ParserState {
lastToken?: string;
groups: Group[];
mode: ParseGroupsMode;
negative: boolean;
}

export const parseOnes = (acc: ParserState, token: string): ParserState => {
if (acc.mode === ParseGroupsMode.THOUSAND_MODE) {
// Create next empty place
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.ONES_MODE,
groups: [...acc.groups, [...EMPTY_PLACE]],
};
}
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.ONES_MODE,
};
};

export const parseTenPlusOnes = (acc: ParserState, token: string): ParserState => {
const tenPlusOnes = TEN_PLUS_ONES.findIndex((t) => t === token);
const lastGroup = acc.groups.at(-1) ?? [...EMPTY_PLACE];
if (acc.mode === ParseGroupsMode.THOUSAND_MODE) {
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TEN_PLUS_ONES_MODE,
groups: [...acc.groups, [`01${tenPlusOnes}` as GroupDigits, lastGroup[GROUP_PLACE_INDEX] - BigInt(1)]],
};
}

lastGroup[GROUP_DIGITS_INDEX] = `${lastGroup[GROUP_DIGITS_INDEX].slice(0, 1)}1${tenPlusOnes}` as GroupDigits;
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TEN_PLUS_ONES_MODE,
groups: [...acc.groups.slice(0, -1), lastGroup],
};
};

export const parseTens = (acc: ParserState, token: string): ParserState => {
const tens = TENS.findIndex((t) => t === token);
const lastGroup = acc.groups.at(-1) ?? [...EMPTY_PLACE];
if (acc.mode === ParseGroupsMode.THOUSAND_MODE) {
return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TENS_MODE,
groups: [...acc.groups, [`0${tens}0` as GroupDigits, lastGroup[GROUP_PLACE_INDEX] - BigInt(1)]],
};
}

lastGroup[GROUP_DIGITS_INDEX] = (
`${lastGroup[GROUP_DIGITS_INDEX].slice(0, 1)}${tens}${lastGroup[GROUP_DIGITS_INDEX].slice(2)}`
) as GroupDigits;

return {
...acc,
lastToken: token,
mode: ParseGroupsMode.TENS_MODE,
groups: [...acc.groups.slice(0, -1), lastGroup],
};
};

Loading…
Cancel
Save