From 15e2d3a29b0d1a304965e34f114a911e5a7abdb3 Mon Sep 17 00:00:00 2001 From: sai-neetha Date: Mon, 20 Mar 2023 08:05:47 +0100 Subject: Odlux Update Add eslint and custom icons update Issue-ID: CCSDK-3871 Signed-off-by: sai-neetha Change-Id: If6b676128cc9cff0437a5dc54f85eaafd3b8c586 Signed-off-by: highstreetherbert --- .../apps/configurationApp/src/yang/whenParser.ts | 235 +++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 sdnr/wt/odlux/apps/configurationApp/src/yang/whenParser.ts (limited to 'sdnr/wt/odlux/apps/configurationApp/src/yang/whenParser.ts') diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/whenParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/whenParser.ts new file mode 100644 index 000000000..fa2968c9c --- /dev/null +++ b/sdnr/wt/odlux/apps/configurationApp/src/yang/whenParser.ts @@ -0,0 +1,235 @@ +enum WhenTokenType { + AND = 'AND', + OR = 'OR', + NOT = 'NOT', + EQUALS = 'EQUALS', + COMMA = 'COMMA', + STRING = 'STRING', + FUNCTION = 'FUNCTION', + IDENTIFIER = 'IDENTIFIER', + OPEN_PAREN = 'OPEN_PAREN', + CLOSE_PAREN = 'CLOSE_PAREN', + EXPRESSION = 'EXPRESSION', +} + +type Token = { + type: WhenTokenType; + value: string; +}; + +const isAlpha = (char: string) => /[a-z]/i.test(char); + +const isAlphaNumeric = (char: string) => /[A-Za-z0-9_\-/:\.]/i.test(char); + +const lex = (input: string) : Token[] => { + let tokens = [] as any[]; + let current = 0; + + while (current < input.length) { + let char = input[current]; + + if (char === ' ') { + current++; + continue; + } + + if (char === '(') { + tokens.push({ type: WhenTokenType.OPEN_PAREN, value: char }); + current++; + continue; + } + + if (char === ')') { + tokens.push({ type: WhenTokenType.CLOSE_PAREN, value: char }); + current++; + continue; + } + + if (char === '=') { + tokens.push({ type: WhenTokenType.EQUALS, value: char }); + current++; + continue; + } + + if (char === ',') { + tokens.push({ type: WhenTokenType.COMMA, value: char }); + current++; + continue; + } + + if (char === '\"' || char === '\'') { + let value = ''; + let start = current; + current++; + + while (current < input.length) { + let innerChar = input[current]; + if (innerChar === '\\') { + value += input[current] + input[current + 1]; + current += 2; + } else if (innerChar === input[start]) { + current++; + break; + } else { + value += innerChar; + current++; + } + } + + tokens.push({ type: WhenTokenType.STRING, value }); + continue; + } + + if (isAlpha(char)) { + let value = ''; + while (isAlpha(char)) { + value += char; + char = input[++current]; + } + + switch (value) { + case 'and': + tokens.push({ type: WhenTokenType.AND }); + break; + case 'or': + tokens.push({ type: WhenTokenType.OR }); + break; + case 'not': + tokens.push({ type: WhenTokenType.NOT }); + break; + case 'eq': + tokens.push({ type: WhenTokenType.EQUALS }); + break; + default: + while (isAlphaNumeric(char)) { + value += char; + char = input[++current]; + } + tokens.push({ type: WhenTokenType.IDENTIFIER, value }); + } + + continue; + } + if (isAlphaNumeric(char)) { + let value = ''; + while (isAlphaNumeric(char)) { + value += char; + char = input[++current]; + } + + tokens.push({ type: WhenTokenType.IDENTIFIER, value }); + continue; + } + throw new TypeError(`I don't know what this character is: ${char}`); + } + return tokens; +}; + +type WhenAST = { + type: WhenTokenType; + left?: WhenAST; + right?: WhenAST; + value?: string | WhenAST; + name?: string; + args?: WhenAST[]; +}; + +const precedence : { [index: string] : number } = { + 'EQUALS': 4, + 'NOT': 3, + 'AND': 2, + 'OR': 1, +}; + +const parseWhen = (whenExpression: string) => { + const tokens = lex(whenExpression); + let current = 0; + + const walk = (precedenceLevel = 0) : WhenAST => { + let token = tokens[current]; + let node: WhenAST | null = null; + + if (token.type === WhenTokenType.OPEN_PAREN) { + token = tokens[++current]; + let innerNode: WhenAST = { type: WhenTokenType.EXPRESSION, value: walk() }; + token = tokens[current]; + + while (token.type !== WhenTokenType.CLOSE_PAREN) { + innerNode = { + type: token.type, + value: token.value, + left: innerNode, + right: walk(), + }; + token = tokens[current]; + } + current++; + return innerNode; + } + + if (token.type === WhenTokenType.STRING ) { + current++; + node = { type: token.type, value: token.value }; + } + + if (token.type === WhenTokenType.NOT) { + token = tokens[++current]; + node = { type: WhenTokenType.NOT, value: token.value, right: walk() }; + } + + if (token.type === WhenTokenType.IDENTIFIER) { + const nextToken = tokens[current + 1]; + if (nextToken.type === WhenTokenType.OPEN_PAREN) { + let name = token.value; + token = tokens[++current]; + + let args = []; + token = tokens[++current]; + + while (token.type !== WhenTokenType.CLOSE_PAREN) { + if (token.type === WhenTokenType.COMMA) { + current++; + } else { + args.push(walk()); + } + token = tokens[current]; + } + + current++; + node = { type: WhenTokenType.FUNCTION, name, args }; + } else { + current++; + node = { type: WhenTokenType.IDENTIFIER, value: token.value }; + } + } + + if (!node) throw new TypeError('Unexpected token: ' + token.type); + + token = tokens[current]; + while (current < tokens.length && precedence[token.type] >= precedenceLevel) { + console.log(current, tokens[current], tokens[current].type, precedenceLevel, precedence[token.type]); + token = tokens[current]; + if (token.type === WhenTokenType.EQUALS || token.type === WhenTokenType.AND || token.type === WhenTokenType.OR) { + current++; + node = { + type: token.type, + left: node, + right: walk(precedence[token.type]), + }; + } else { + break; + } + } + + return node; + + }; + + return walk(); +}; + +export { + parseWhen, + WhenAST, + WhenTokenType, +}; \ No newline at end of file -- cgit 1.2.3-korg