add find-closing-brace util function

This commit is contained in:
Kurt Hutten IrevDev
2022-11-17 16:06:38 +11:00
parent 7b0a102e98
commit e89241de92
2 changed files with 73 additions and 1 deletions

View File

@ -1,6 +1,24 @@
import { abstractSyntaxTree } from "./abstractSyntaxTree";
import { abstractSyntaxTree, findClosingBrace } from "./abstractSyntaxTree";
import { lexer } from "./tokeniser";
describe("findClosingBrace", () => {
test("finds the closing brace", () => {
const basic = "( hey )"
expect(findClosingBrace(lexer(basic), 0)).toBe(4)
const handlesNonZeroIndex = "(indexForBracketToRightOfThisIsTwo(shouldBeFour)AndNotThisSix)"
expect(findClosingBrace(lexer(handlesNonZeroIndex), 2)).toBe(4)
expect(findClosingBrace(lexer(handlesNonZeroIndex), 0)).toBe(6)
const handlesNested = "{a{b{c(}d]}eathou athoeu tah u} thatOneToTheLeftIsLast }"
expect(findClosingBrace(lexer(handlesNested), 0)).toBe(18)
// throws when not started on a brace
expect(() => findClosingBrace(lexer(handlesNested), 1)).toThrow()
})
})
describe("testing AST", () => {
test("test 5 + 6", () => {
const tokens = lexer("5 +6");

View File

@ -402,3 +402,57 @@ export const abstractSyntaxTree = (tokens: Token[]): Program => {
};
return program;
};
export function findClosingBrace(
tokens: Token[],
index: number,
_braceCount: number = 0,
_searchOpeningBrace: string = ""
): number {
const closingBraceMap: { [key: string]: string } = {
"(": ")",
"{": "}",
"[": "]",
};
const currentToken = tokens[index];
let searchOpeningBrace = _searchOpeningBrace;
const isFirstCall = !searchOpeningBrace && _braceCount === 0;
if (isFirstCall) {
searchOpeningBrace = currentToken.value;
if (!["(", "{", "["].includes(searchOpeningBrace)) {
throw new Error(
`expected to be started on a opening brace ( { [, instead found '${searchOpeningBrace}'`
);
}
}
const foundClosingBrace =
_braceCount === 1 &&
currentToken.value === closingBraceMap[searchOpeningBrace];
const foundAnotherOpeningBrace = currentToken.value === searchOpeningBrace;
const foundAnotherClosingBrace =
currentToken.value === closingBraceMap[searchOpeningBrace];
if (foundClosingBrace) {
return index;
}
if (foundAnotherOpeningBrace) {
return findClosingBrace(
tokens,
index + 1,
_braceCount + 1,
searchOpeningBrace
);
}
if (foundAnotherClosingBrace) {
return findClosingBrace(
tokens,
index + 1,
_braceCount - 1,
searchOpeningBrace
);
}
// non-brace token, increment and continue
return findClosingBrace(tokens, index + 1, _braceCount, searchOpeningBrace);
}