pbi-parsers 0.7.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pbi_parsers/__init__.py +9 -0
- pbi_parsers/base/__init__.py +7 -0
- pbi_parsers/base/lexer.py +127 -0
- pbi_parsers/base/tokens.py +61 -0
- pbi_parsers/dax/__init__.py +22 -0
- pbi_parsers/dax/exprs/__init__.py +107 -0
- pbi_parsers/dax/exprs/_base.py +46 -0
- pbi_parsers/dax/exprs/_utils.py +45 -0
- pbi_parsers/dax/exprs/add_sub.py +73 -0
- pbi_parsers/dax/exprs/add_sub_unary.py +72 -0
- pbi_parsers/dax/exprs/array.py +75 -0
- pbi_parsers/dax/exprs/column.py +56 -0
- pbi_parsers/dax/exprs/comparison.py +76 -0
- pbi_parsers/dax/exprs/concatenation.py +73 -0
- pbi_parsers/dax/exprs/div_mul.py +75 -0
- pbi_parsers/dax/exprs/exponent.py +67 -0
- pbi_parsers/dax/exprs/function.py +102 -0
- pbi_parsers/dax/exprs/hierarchy.py +68 -0
- pbi_parsers/dax/exprs/identifier.py +46 -0
- pbi_parsers/dax/exprs/ins.py +67 -0
- pbi_parsers/dax/exprs/keyword.py +60 -0
- pbi_parsers/dax/exprs/literal_number.py +46 -0
- pbi_parsers/dax/exprs/literal_string.py +45 -0
- pbi_parsers/dax/exprs/logical.py +76 -0
- pbi_parsers/dax/exprs/measure.py +44 -0
- pbi_parsers/dax/exprs/none.py +30 -0
- pbi_parsers/dax/exprs/parens.py +61 -0
- pbi_parsers/dax/exprs/returns.py +76 -0
- pbi_parsers/dax/exprs/table.py +51 -0
- pbi_parsers/dax/exprs/variable.py +68 -0
- pbi_parsers/dax/formatter.py +215 -0
- pbi_parsers/dax/lexer.py +222 -0
- pbi_parsers/dax/main.py +63 -0
- pbi_parsers/dax/parser.py +66 -0
- pbi_parsers/dax/tokens.py +54 -0
- pbi_parsers/dax/utils.py +120 -0
- pbi_parsers/pq/__init__.py +17 -0
- pbi_parsers/pq/exprs/__init__.py +98 -0
- pbi_parsers/pq/exprs/_base.py +33 -0
- pbi_parsers/pq/exprs/_utils.py +31 -0
- pbi_parsers/pq/exprs/add_sub.py +59 -0
- pbi_parsers/pq/exprs/add_sub_unary.py +57 -0
- pbi_parsers/pq/exprs/and_or_expr.py +60 -0
- pbi_parsers/pq/exprs/array.py +53 -0
- pbi_parsers/pq/exprs/arrow.py +50 -0
- pbi_parsers/pq/exprs/column.py +42 -0
- pbi_parsers/pq/exprs/comparison.py +62 -0
- pbi_parsers/pq/exprs/concatenation.py +61 -0
- pbi_parsers/pq/exprs/div_mul.py +59 -0
- pbi_parsers/pq/exprs/each.py +41 -0
- pbi_parsers/pq/exprs/ellipsis_expr.py +28 -0
- pbi_parsers/pq/exprs/function.py +63 -0
- pbi_parsers/pq/exprs/identifier.py +77 -0
- pbi_parsers/pq/exprs/if_expr.py +70 -0
- pbi_parsers/pq/exprs/is_expr.py +54 -0
- pbi_parsers/pq/exprs/keyword.py +40 -0
- pbi_parsers/pq/exprs/literal_number.py +31 -0
- pbi_parsers/pq/exprs/literal_string.py +31 -0
- pbi_parsers/pq/exprs/meta.py +54 -0
- pbi_parsers/pq/exprs/negation.py +52 -0
- pbi_parsers/pq/exprs/none.py +22 -0
- pbi_parsers/pq/exprs/not_expr.py +39 -0
- pbi_parsers/pq/exprs/parens.py +43 -0
- pbi_parsers/pq/exprs/record.py +58 -0
- pbi_parsers/pq/exprs/row.py +54 -0
- pbi_parsers/pq/exprs/row_index.py +57 -0
- pbi_parsers/pq/exprs/statement.py +67 -0
- pbi_parsers/pq/exprs/try_expr.py +55 -0
- pbi_parsers/pq/exprs/type_expr.py +78 -0
- pbi_parsers/pq/exprs/variable.py +52 -0
- pbi_parsers/pq/formatter.py +13 -0
- pbi_parsers/pq/lexer.py +219 -0
- pbi_parsers/pq/main.py +63 -0
- pbi_parsers/pq/parser.py +65 -0
- pbi_parsers/pq/tokens.py +81 -0
- pbi_parsers-0.7.8.dist-info/METADATA +66 -0
- pbi_parsers-0.7.8.dist-info/RECORD +78 -0
- pbi_parsers-0.7.8.dist-info/WHEEL +4 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from pbi_parsers.pq.tokens import TokenType
|
4
|
+
|
5
|
+
from ._base import Expression
|
6
|
+
from ._utils import lexer_reset
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
from pbi_parsers.pq.parser import Parser
|
10
|
+
|
11
|
+
|
12
|
+
class NotExpression(Expression):
|
13
|
+
expr: Expression
|
14
|
+
|
15
|
+
def __init__(
|
16
|
+
self,
|
17
|
+
expr: Expression,
|
18
|
+
) -> None:
|
19
|
+
self.expr = expr
|
20
|
+
|
21
|
+
def pprint(self) -> str:
|
22
|
+
return f"Not ({self.expr.pprint()})"
|
23
|
+
|
24
|
+
@classmethod
|
25
|
+
@lexer_reset
|
26
|
+
def match(cls, parser: "Parser") -> "NotExpression | None":
|
27
|
+
from . import any_expression_match # noqa: PLC0415
|
28
|
+
|
29
|
+
if parser.consume().tok_type != TokenType.NOT:
|
30
|
+
return None
|
31
|
+
|
32
|
+
expr = any_expression_match(parser)
|
33
|
+
if expr is None:
|
34
|
+
return None
|
35
|
+
return NotExpression(expr=expr)
|
36
|
+
|
37
|
+
def children(self) -> list[Expression]:
|
38
|
+
"""Returns a list of child expressions."""
|
39
|
+
return [self.expr]
|
@@ -0,0 +1,43 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from pbi_parsers.pq.tokens import TokenType
|
4
|
+
|
5
|
+
from ._base import Expression
|
6
|
+
from ._utils import lexer_reset
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
from pbi_parsers.pq.parser import Parser
|
10
|
+
|
11
|
+
|
12
|
+
class ParenthesesExpression(Expression):
|
13
|
+
inner_statement: Expression | None
|
14
|
+
|
15
|
+
def __init__(self, inner_statement: Expression | None) -> None:
|
16
|
+
self.inner_statement = inner_statement
|
17
|
+
|
18
|
+
def pprint(self) -> str:
|
19
|
+
return f"""
|
20
|
+
Parentheses (
|
21
|
+
{self.inner_statement}
|
22
|
+
)""".strip()
|
23
|
+
|
24
|
+
@classmethod
|
25
|
+
@lexer_reset
|
26
|
+
def match(cls, parser: "Parser") -> "ParenthesesExpression | None":
|
27
|
+
from . import any_expression_match # noqa: PLC0415
|
28
|
+
|
29
|
+
if not cls.match_tokens(parser, [TokenType.LEFT_PAREN]):
|
30
|
+
return None
|
31
|
+
|
32
|
+
parser.consume()
|
33
|
+
# when paired with an arrow expression, the value may not exist
|
34
|
+
value = any_expression_match(parser)
|
35
|
+
|
36
|
+
if parser.consume().tok_type != TokenType.RIGHT_PAREN:
|
37
|
+
return None
|
38
|
+
|
39
|
+
return ParenthesesExpression(inner_statement=value)
|
40
|
+
|
41
|
+
def children(self) -> list[Expression]:
|
42
|
+
"""Returns a list of child expressions."""
|
43
|
+
return [self.inner_statement] if self.inner_statement else []
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import textwrap
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from pbi_parsers.pq.tokens import TokenType
|
5
|
+
|
6
|
+
from ._base import Expression
|
7
|
+
from ._utils import lexer_reset
|
8
|
+
from .identifier import IdentifierExpression
|
9
|
+
|
10
|
+
if TYPE_CHECKING:
|
11
|
+
from pbi_parsers.pq.parser import Parser
|
12
|
+
|
13
|
+
|
14
|
+
class RecordExpression(Expression):
|
15
|
+
args: list[tuple[IdentifierExpression, Expression]]
|
16
|
+
|
17
|
+
def __init__(self, args: list[tuple[IdentifierExpression, Expression]]) -> None:
|
18
|
+
self.args = args
|
19
|
+
|
20
|
+
def pprint(self) -> str:
|
21
|
+
args = ",\n".join(f"{arg[0].pprint()}: {arg[1].pprint()}" for arg in self.args)
|
22
|
+
args = textwrap.indent(args, " " * 4)[4:]
|
23
|
+
return f"""
|
24
|
+
Record (
|
25
|
+
{args}
|
26
|
+
) """.strip()
|
27
|
+
|
28
|
+
@classmethod
|
29
|
+
@lexer_reset
|
30
|
+
def match(cls, parser: "Parser") -> "RecordExpression | None":
|
31
|
+
from . import any_expression_match # noqa: PLC0415
|
32
|
+
|
33
|
+
args: list[tuple[IdentifierExpression, Expression]] = []
|
34
|
+
if parser.consume().tok_type != TokenType.LEFT_BRACKET:
|
35
|
+
return None
|
36
|
+
|
37
|
+
while parser.peek().tok_type != TokenType.RIGHT_BRACKET:
|
38
|
+
name = IdentifierExpression.match(parser)
|
39
|
+
if name is None:
|
40
|
+
return None
|
41
|
+
if parser.consume().tok_type != TokenType.EQUAL_SIGN:
|
42
|
+
return None
|
43
|
+
|
44
|
+
value = any_expression_match(parser)
|
45
|
+
if value is None:
|
46
|
+
return None
|
47
|
+
|
48
|
+
args.append((name, value))
|
49
|
+
|
50
|
+
if parser.peek().tok_type == TokenType.COMMA:
|
51
|
+
parser.consume()
|
52
|
+
|
53
|
+
parser.consume() # consume the right bracket
|
54
|
+
return RecordExpression(args=args)
|
55
|
+
|
56
|
+
def children(self) -> list[Expression]:
|
57
|
+
"""Returns a list of child expressions."""
|
58
|
+
return [val for arg in self.args for val in arg]
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import textwrap
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from pbi_parsers.pq.tokens import TokenType
|
5
|
+
|
6
|
+
from ._base import Expression
|
7
|
+
from ._utils import lexer_reset
|
8
|
+
from .identifier import IdentifierExpression
|
9
|
+
|
10
|
+
if TYPE_CHECKING:
|
11
|
+
from pbi_parsers.pq.parser import Parser
|
12
|
+
|
13
|
+
|
14
|
+
class RowExpression(Expression):
|
15
|
+
table: IdentifierExpression
|
16
|
+
indexer: Expression
|
17
|
+
|
18
|
+
def __init__(
|
19
|
+
self,
|
20
|
+
table: IdentifierExpression,
|
21
|
+
indexer: Expression,
|
22
|
+
) -> None:
|
23
|
+
self.table = table
|
24
|
+
self.indexer = indexer
|
25
|
+
|
26
|
+
def pprint(self) -> str:
|
27
|
+
indexer = textwrap.indent(self.indexer.pprint(), " " * 4)[4:]
|
28
|
+
return f"""
|
29
|
+
Table (
|
30
|
+
name: {self.table.pprint()},
|
31
|
+
indexer: {indexer}
|
32
|
+
) """.strip()
|
33
|
+
|
34
|
+
@classmethod
|
35
|
+
@lexer_reset
|
36
|
+
def match(cls, parser: "Parser") -> "RowExpression | None":
|
37
|
+
from . import any_expression_match # noqa: PLC0415
|
38
|
+
|
39
|
+
table = IdentifierExpression.match(parser)
|
40
|
+
if table is None:
|
41
|
+
return None
|
42
|
+
if parser.consume().tok_type != TokenType.LEFT_CURLY_BRACE:
|
43
|
+
return None
|
44
|
+
indexer = any_expression_match(parser)
|
45
|
+
if indexer is None:
|
46
|
+
return None
|
47
|
+
if parser.consume().tok_type != TokenType.RIGHT_CURLY_BRACE:
|
48
|
+
return None
|
49
|
+
|
50
|
+
return RowExpression(table=table, indexer=indexer)
|
51
|
+
|
52
|
+
def children(self) -> list[Expression]:
|
53
|
+
"""Returns a list of child expressions."""
|
54
|
+
return [self.table, self.indexer]
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import textwrap
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from pbi_parsers.pq.tokens import TokenType
|
5
|
+
|
6
|
+
from ._base import Expression
|
7
|
+
from ._utils import lexer_reset
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from pbi_parsers.pq.parser import Parser
|
11
|
+
|
12
|
+
|
13
|
+
class RowIndexExpression(Expression):
|
14
|
+
table: Expression
|
15
|
+
indexer: Expression
|
16
|
+
|
17
|
+
def __init__(self, table: Expression, indexer: Expression) -> None:
|
18
|
+
self.table = table
|
19
|
+
self.indexer = indexer
|
20
|
+
|
21
|
+
def pprint(self) -> str:
|
22
|
+
table = textwrap.indent(self.table.pprint(), " " * 4)[4:]
|
23
|
+
indexer = textwrap.indent(self.indexer.pprint(), " " * 4)[4:]
|
24
|
+
return f"""
|
25
|
+
Indexer (
|
26
|
+
table: {table},
|
27
|
+
indexer: {indexer}
|
28
|
+
) """.strip()
|
29
|
+
|
30
|
+
@classmethod
|
31
|
+
@lexer_reset
|
32
|
+
def match(cls, parser: "Parser") -> "RowIndexExpression | None":
|
33
|
+
from . import EXPRESSION_HIERARCHY, any_expression_match # noqa: PLC0415
|
34
|
+
|
35
|
+
skip_index = EXPRESSION_HIERARCHY.index(
|
36
|
+
RowIndexExpression,
|
37
|
+
) # intentionally inclusive of self to allow +-++- chains
|
38
|
+
|
39
|
+
table = any_expression_match(parser, skip_first=skip_index + 1)
|
40
|
+
if table is None:
|
41
|
+
return None
|
42
|
+
|
43
|
+
if parser.consume().tok_type != TokenType.LEFT_BRACKET:
|
44
|
+
return None
|
45
|
+
|
46
|
+
indexer = any_expression_match(parser)
|
47
|
+
if indexer is None:
|
48
|
+
return None
|
49
|
+
|
50
|
+
if parser.consume().tok_type != TokenType.RIGHT_BRACKET:
|
51
|
+
return None
|
52
|
+
|
53
|
+
return RowIndexExpression(table=table, indexer=indexer)
|
54
|
+
|
55
|
+
def children(self) -> list[Expression]:
|
56
|
+
"""Returns a list of child expressions."""
|
57
|
+
return [self.table, self.indexer]
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import textwrap
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from pbi_parsers.pq.tokens import TokenType
|
5
|
+
|
6
|
+
from ._base import Expression
|
7
|
+
from ._utils import lexer_reset
|
8
|
+
from .variable import VariableExpression
|
9
|
+
|
10
|
+
if TYPE_CHECKING:
|
11
|
+
from pbi_parsers.pq.parser import Parser
|
12
|
+
|
13
|
+
|
14
|
+
class StatementExpression(Expression):
|
15
|
+
statements: list[VariableExpression]
|
16
|
+
let_expr: Expression
|
17
|
+
|
18
|
+
def __init__(self, let_expr: Expression, statements: list[VariableExpression]) -> None:
|
19
|
+
self.let_expr = let_expr
|
20
|
+
self.statements = statements
|
21
|
+
|
22
|
+
def pprint(self) -> str:
|
23
|
+
let_expr = textwrap.indent(self.let_expr.pprint(), " " * 14)[14:]
|
24
|
+
statements = textwrap.indent(
|
25
|
+
",\n".join(statement.pprint() for statement in self.statements),
|
26
|
+
" " * 17,
|
27
|
+
)[17:]
|
28
|
+
return f"""
|
29
|
+
Statement (
|
30
|
+
statements: {statements}
|
31
|
+
let_expr: {let_expr}
|
32
|
+
)
|
33
|
+
""".strip()
|
34
|
+
|
35
|
+
@classmethod
|
36
|
+
@lexer_reset
|
37
|
+
def match(cls, parser: "Parser") -> "StatementExpression | None":
|
38
|
+
from . import any_expression_match # noqa: PLC0415
|
39
|
+
|
40
|
+
if parser.consume().tok_type != TokenType.LET:
|
41
|
+
return None
|
42
|
+
|
43
|
+
statements = []
|
44
|
+
while parser.peek().tok_type != TokenType.IN:
|
45
|
+
statements.append(VariableExpression.match(parser))
|
46
|
+
|
47
|
+
if parser.peek().tok_type == TokenType.COMMA:
|
48
|
+
parser.consume()
|
49
|
+
elif parser.peek().tok_type != TokenType.IN:
|
50
|
+
msg = f"Expected a comma or 'in' token, got {parser.peek().tok_type}"
|
51
|
+
raise ValueError(msg)
|
52
|
+
if not statements:
|
53
|
+
return None
|
54
|
+
|
55
|
+
if parser.consume().tok_type != TokenType.IN:
|
56
|
+
msg = "Expected 'in' token after let statements"
|
57
|
+
raise ValueError(msg)
|
58
|
+
|
59
|
+
in_expr = any_expression_match(parser)
|
60
|
+
if in_expr is None:
|
61
|
+
msg = "Expected an expression after 'in' token"
|
62
|
+
raise ValueError(msg)
|
63
|
+
return StatementExpression(statements=statements, let_expr=in_expr)
|
64
|
+
|
65
|
+
def children(self) -> list[Expression]:
|
66
|
+
"""Returns a list of child expressions."""
|
67
|
+
return [self.let_expr, *self.statements]
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import textwrap
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from pbi_parsers.pq.tokens import TokenType
|
5
|
+
|
6
|
+
from ._base import Expression
|
7
|
+
from ._utils import lexer_reset
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from pbi_parsers.pq.parser import Parser
|
11
|
+
|
12
|
+
|
13
|
+
class TryExpression(Expression):
|
14
|
+
try_expr: Expression
|
15
|
+
otherwise_expr: Expression
|
16
|
+
|
17
|
+
def __init__(self, try_expr: Expression, otherwise_expr: Expression) -> None:
|
18
|
+
self.try_expr = try_expr
|
19
|
+
self.otherwise_expr = otherwise_expr
|
20
|
+
|
21
|
+
def pprint(self) -> str:
|
22
|
+
try_expr = textwrap.indent(self.try_expr.pprint(), " " * 10)[10:]
|
23
|
+
otherwise_expr = textwrap.indent(self.otherwise_expr.pprint(), " " * 10)[10:]
|
24
|
+
return f"""
|
25
|
+
Try (
|
26
|
+
try: {try_expr},
|
27
|
+
otherwise: {otherwise_expr}
|
28
|
+
)""".strip()
|
29
|
+
|
30
|
+
@classmethod
|
31
|
+
@lexer_reset
|
32
|
+
def match(cls, parser: "Parser") -> "TryExpression | None":
|
33
|
+
from . import any_expression_match # noqa: PLC0415
|
34
|
+
|
35
|
+
try_ = parser.consume()
|
36
|
+
if try_.tok_type != TokenType.TRY:
|
37
|
+
return None
|
38
|
+
try_expr: Expression | None = any_expression_match(
|
39
|
+
parser,
|
40
|
+
) # this expression can recurse
|
41
|
+
if not try_expr:
|
42
|
+
return None
|
43
|
+
|
44
|
+
otherwise = parser.consume()
|
45
|
+
if otherwise.tok_type != TokenType.OTHERWISE:
|
46
|
+
return None
|
47
|
+
otherwise_expr = any_expression_match(parser)
|
48
|
+
if not otherwise_expr:
|
49
|
+
return None
|
50
|
+
|
51
|
+
return TryExpression(try_expr=try_expr, otherwise_expr=otherwise_expr)
|
52
|
+
|
53
|
+
def children(self) -> list[Expression]:
|
54
|
+
"""Returns a list of child expressions."""
|
55
|
+
return [self.try_expr, self.otherwise_expr]
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import textwrap
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from pbi_parsers.pq.tokens import Token, TokenType
|
5
|
+
|
6
|
+
from ._base import Expression
|
7
|
+
from ._utils import lexer_reset
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from pbi_parsers.pq.parser import Parser
|
11
|
+
|
12
|
+
|
13
|
+
class TypingExpression(Expression):
|
14
|
+
type_name: list[Token]
|
15
|
+
nullable: Token | None = None
|
16
|
+
column_mapping: Expression | None = None
|
17
|
+
|
18
|
+
def __init__(
|
19
|
+
self,
|
20
|
+
type_name: list[Token],
|
21
|
+
nullable: Token | None = None,
|
22
|
+
column_mapping: Expression | None = None,
|
23
|
+
) -> None:
|
24
|
+
self.tok_type_name = type_name
|
25
|
+
self.nullable = nullable
|
26
|
+
self.column_mapping = column_mapping
|
27
|
+
|
28
|
+
def pprint(self) -> str:
|
29
|
+
type_name = ".".join(t.text for t in self.tok_type_name)
|
30
|
+
if self.column_mapping is None:
|
31
|
+
base = f"Type ({type_name})"
|
32
|
+
else:
|
33
|
+
column_mapping = textwrap.indent(self.column_mapping.pprint(), " " * 10)[10:]
|
34
|
+
base = f"""
|
35
|
+
Type (
|
36
|
+
type: {type_name},
|
37
|
+
column: {column_mapping}
|
38
|
+
)
|
39
|
+
"""
|
40
|
+
return base
|
41
|
+
|
42
|
+
@classmethod
|
43
|
+
@lexer_reset
|
44
|
+
def match(cls, parser: "Parser") -> "TypingExpression | None":
|
45
|
+
from . import any_expression_match # noqa: PLC0415
|
46
|
+
|
47
|
+
type_keyword = parser.consume()
|
48
|
+
if type_keyword.tok_type == TokenType.TYPE_LITERAL:
|
49
|
+
return TypingExpression(type_name=[type_keyword])
|
50
|
+
if type_keyword.tok_type != TokenType.TYPE:
|
51
|
+
return None
|
52
|
+
|
53
|
+
nullable = None
|
54
|
+
if parser.peek().tok_type == TokenType.NULLABLE:
|
55
|
+
nullable = parser.consume()
|
56
|
+
|
57
|
+
name_parts = [parser.consume()]
|
58
|
+
# single part name (i.e. no period)
|
59
|
+
while parser.peek().tok_type == TokenType.PERIOD:
|
60
|
+
period, name = parser.consume(), parser.consume()
|
61
|
+
if name.tok_type not in {TokenType.UNQUOTED_IDENTIFIER, TokenType.TYPE}:
|
62
|
+
return None
|
63
|
+
if period.tok_type != TokenType.PERIOD:
|
64
|
+
return None
|
65
|
+
name_parts.append(name)
|
66
|
+
if len(name_parts) == 1 and name_parts[0].text == "table":
|
67
|
+
column_mapping = any_expression_match(parser)
|
68
|
+
else:
|
69
|
+
column_mapping = None
|
70
|
+
return TypingExpression(
|
71
|
+
type_name=name_parts,
|
72
|
+
nullable=nullable,
|
73
|
+
column_mapping=column_mapping,
|
74
|
+
)
|
75
|
+
|
76
|
+
def children(self) -> list[Expression]:
|
77
|
+
"""Returns a list of child expressions."""
|
78
|
+
return [self.column_mapping] if self.column_mapping else []
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import textwrap
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from pbi_parsers.pq.tokens import Token, TokenType
|
5
|
+
|
6
|
+
from ._base import Expression
|
7
|
+
from ._utils import lexer_reset
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from pbi_parsers.pq.parser import Parser
|
11
|
+
|
12
|
+
|
13
|
+
class VariableExpression(Expression):
|
14
|
+
var_name: Token
|
15
|
+
statement: Expression
|
16
|
+
|
17
|
+
def __init__(self, var_name: Token, statement: Expression) -> None:
|
18
|
+
self.var_name = var_name
|
19
|
+
self.statement = statement
|
20
|
+
|
21
|
+
def pprint(self) -> str:
|
22
|
+
statement = textwrap.indent(self.statement.pprint(), " " * 17).lstrip()
|
23
|
+
return f"""
|
24
|
+
Variable (
|
25
|
+
name: {self.var_name.text},
|
26
|
+
statement: {statement}
|
27
|
+
)
|
28
|
+
""".strip()
|
29
|
+
|
30
|
+
@classmethod
|
31
|
+
@lexer_reset
|
32
|
+
def match(cls, parser: "Parser") -> "VariableExpression | None":
|
33
|
+
from . import any_expression_match # noqa: PLC0415
|
34
|
+
|
35
|
+
var_name = parser.consume()
|
36
|
+
equal_sign = parser.consume()
|
37
|
+
if (
|
38
|
+
var_name.tok_type
|
39
|
+
not in {TokenType.QUOTED_IDENTIFER, TokenType.UNQUOTED_IDENTIFIER, TokenType.HASH_IDENTIFIER}
|
40
|
+
or equal_sign.tok_type != TokenType.EQUAL_SIGN
|
41
|
+
):
|
42
|
+
return None
|
43
|
+
|
44
|
+
statement = any_expression_match(parser)
|
45
|
+
if statement is None:
|
46
|
+
msg = "VariableExpression.match called without valid inner expression"
|
47
|
+
raise ValueError(msg)
|
48
|
+
return VariableExpression(var_name=var_name, statement=statement)
|
49
|
+
|
50
|
+
def children(self) -> list[Expression]:
|
51
|
+
"""Returns a list of child expressions."""
|
52
|
+
return [self.statement]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from .exprs import Expression
|
2
|
+
|
3
|
+
|
4
|
+
class Formatter:
|
5
|
+
expression: Expression
|
6
|
+
|
7
|
+
def __init__(self, expression: Expression) -> None:
|
8
|
+
self.expression = expression
|
9
|
+
|
10
|
+
def format(self) -> str:
|
11
|
+
# Implement the formatting logic here
|
12
|
+
msg = "Formatter.format method is not implemented."
|
13
|
+
raise NotImplementedError(msg)
|