@borgar/fx
Version:
Utilities for working with Excel formulas
61 lines (58 loc) • 1.73 kB
text/typescript
import { REF_NAMED } from '../constants.ts';
import type { Token } from '../types.ts';
// The advertized named ranges rules are a bit off from what Excel seems to do.
// In the "extended range" of chars, it looks like it allows most things above
// U+00B0 with the range between U+00A0-U+00AF rather random:
// /^[a-zA-Z\\_¡¤§¨ª\u00ad¯\u00b0-\uffff][a-zA-Z0-9\\_.?¡¤§¨ª\u00ad¯\u00b0-\uffff]{0,254}/
//
// I've simplified to allowing everything above U+00A1:
// /^[a-zA-Z\\_\u00a1-\uffff][a-zA-Z0-9\\_.?\u00a1-\uffff]{0,254}/
export function lexNamed (str: string, pos: number): Token | undefined {
const start = pos;
// starts with: [a-zA-Z\\_\u00a1-\uffff]
const s = str.charCodeAt(pos);
if (
(s >= 65 && s <= 90) || // A-Z
(s >= 97 && s <= 122) || // a-z
(s === 95) || // _
(s === 92) || // \
(s > 0xA0) // \u00a1-\uffff
) {
pos++;
}
else {
return;
}
// has any number of: [a-zA-Z0-9\\_.?\u00a1-\uffff]
let c: number;
do {
c = str.charCodeAt(pos);
if (
(c >= 65 && c <= 90) || // A-Z
(c >= 97 && c <= 122) || // a-z
(c >= 48 && c <= 57) || // 0-9
(c === 95) || // _
(c === 92) || // \
(c === 46) || // .
(c === 63) || // ?
(c > 0xA0) // \u00a1-\uffff
) {
pos++;
}
else {
break;
}
} while (isFinite(c));
const len = pos - start;
if (len && len < 255) {
// names starting with \ must be at least 3 char long
if (s === 92 && len < 3) {
return;
}
// single characters R and C are forbidden as names
if (len === 1 && (s === 114 || s === 82 || s === 99 || s === 67)) {
return;
}
return { type: REF_NAMED, value: str.slice(start, pos) };
}
}