MCPcopy Create free account
hub / github.com/pytest-dev/pytest / Scanner

Class Scanner

src/_pytest/mark/expression.py:72–127  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

70
71
72class Scanner:
73 __slots__ = ("tokens", "current")
74
75 def __init__(self, input: str) -> None:
76 self.tokens = self.lex(input)
77 self.current = next(self.tokens)
78
79 def lex(self, input: str) -> Iterator[Token]:
80 pos = 0
81 while pos < len(input):
82 if input[pos] in (" ", "\t"):
83 pos += 1
84 elif input[pos] == "(":
85 yield Token(TokenType.LPAREN, "(", pos)
86 pos += 1
87 elif input[pos] == ")":
88 yield Token(TokenType.RPAREN, ")", pos)
89 pos += 1
90 else:
91 match = re.match(r"(:?\w|:|\+|-|\.|\[|\]|\\|/)+", input[pos:])
92 if match:
93 value = match.group(0)
94 if value == "or":
95 yield Token(TokenType.OR, value, pos)
96 elif value == "and":
97 yield Token(TokenType.AND, value, pos)
98 elif value == "not":
99 yield Token(TokenType.NOT, value, pos)
100 else:
101 yield Token(TokenType.IDENT, value, pos)
102 pos += len(value)
103 else:
104 raise ParseError(
105 pos + 1,
106 f'unexpected character "{input[pos]}"',
107 )
108 yield Token(TokenType.EOF, "", pos)
109
110 def accept(self, type: TokenType, *, reject: bool = False) -> Optional[Token]:
111 if self.current.type is type:
112 token = self.current
113 if token.type is not TokenType.EOF:
114 self.current = next(self.tokens)
115 return token
116 if reject:
117 self.reject((type,))
118 return None
119
120 def reject(self, expected: Sequence[TokenType]) -> "NoReturn":
121 raise ParseError(
122 self.current.pos + 1,
123 "expected {}; got {}".format(
124 " OR ".join(type.value for type in expected),
125 self.current.type.value,
126 ),
127 )
128
129

Callers 1

compileMethod · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected