Files
nx_post_support/server/src/tools/parser.py
T

74 lines
2.4 KiB
Python

import io
from typing import Optional, Tuple
from tclint.parser import Parser
from tclint.commands import CommandArgError
from tclint.syntax_tree import (
BracedWord,
BareWord,
BracedExpression,
List,
QuotedWord,
Expression,
)
from tclint.lexer import TclSyntaxError, Lexer, TOK_EOF
class CustomParser(Parser):
def __init__(self, debug=False, command_plugins=None):
super().__init__(debug, command_plugins)
# Used to normalize newlines consistently with open()'s universal newlines mode.
self._decoder = io.IncrementalNewlineDecoder(None, True)
def parse(self, script: str, pos: Optional[Tuple[int, int]] = None):
script = self._decoder.decode(script, True)
lexer = Lexer(pos=pos)
lexer.input(script)
tree = self._parse_script(lexer, in_command_sub=False)
assert lexer.type() == TOK_EOF, (
"Didn't reach EOF parsing script, please file a bug report."
)
return tree
def _parse_operator(self, ts):
pos = ts.pos()
# hacky logic to handle parsing legal operators
if ts.value() in {"*", "&", "|"}:
# one or two of these characters are legal operators
operator = ts.value()
ts.next()
if ts.value() == operator:
operator += ts.value()
ts.next()
elif ts.value() in {"<", ">"}:
operator = ts.value()
ts.next()
if ts.value() in {operator, "="}:
operator += ts.value()
ts.next()
elif ts.value() in {"=", "!"}:
operator = ts.value()
ts.next()
if ts.value() != "=":
raise TclSyntaxError(
f"invalid operator in expression: {operator}", pos, ts.pos()
)
operator += ts.value()
ts.next()
elif ts.value() in {"*", "/", "%", "+", "-", "^", "eq", "ne", "in", "ni"}:
operator = ts.value()
ts.next()
else:
message = "invalid operator in expression: "
if ts.value() == "\\ ":
message += (
"\\ (check for trailing whitespace if it's the end of the line)"
)
else:
message += ts.value()
raise TclSyntaxError(message, pos, ts.pos())
return BareWord(operator, pos=pos, end_pos=ts.pos())