• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SPF-OST / trnsys-dck-parser / 8925041585

02 May 2024 01:52PM UTC coverage: 0.0%. First build
8925041585

push

github

web-flow
Merge pull request #1 from SPF-OST/expressions

Expressions

0 of 401 new or added lines in 9 files covered. (0.0%)

0 of 401 relevant lines covered (0.0%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/trnsys_dck_parser/parse/expression/parse.py
NEW
1
import dataclasses as _dc
×
NEW
2
import typing as _tp
×
3

NEW
4
import trnsys_dck_parser.model.expression as _exp
×
NEW
5
import trnsys_dck_parser.parse.common as _pcom
×
NEW
6
import trnsys_dck_parser.parse.expression.tokenize as _petok
×
NEW
7
import trnsys_dck_parser.parse.tokens as _ptok
×
8

9

NEW
10
@_dc.dataclass
×
NEW
11
class ExpressionWithRemainingStartIndex:
×
NEW
12
    expression: _exp.Expression
×
NEW
13
    remaining_input_string_start_index: int
×
14

15

NEW
16
ParseResult = _pcom.ParseResult[_exp.Expression]
×
17

18

NEW
19
class Parser(_pcom.ParserBase[_exp.Expression]):
×
NEW
20
    def __init__(self, input_string: str) -> None:
×
NEW
21
        lexer = _petok.create_lexer(input_string)
×
NEW
22
        super().__init__(lexer)
×
23

NEW
24
    def parse(self) -> ParseResult:
×
NEW
25
        try:
×
NEW
26
            expression = self._expression()
×
NEW
27
            parse_success = _pcom.ParseSuccess(expression, self._remaining_input_string_start_index)
×
NEW
28
            return parse_success
×
NEW
29
        except _pcom.ParseErrorException as exception:
×
NEW
30
            return exception.parse_error
×
31

NEW
32
    def _expression(self) -> _exp.Expression:
×
NEW
33
        addend = self._addend()
×
NEW
34
        while True:
×
NEW
35
            if self._accept(_petok.Tokens.PLUS):
×
NEW
36
                next_addend = self._addend()
×
NEW
37
                addend += next_addend
×
NEW
38
            elif self._accept(_petok.Tokens.MINUS):
×
NEW
39
                next_addend = self._addend()
×
NEW
40
                addend -= next_addend
×
41
            else:
NEW
42
                break
×
43

NEW
44
        return addend
×
45

NEW
46
    def _addend(self) -> _exp.Expression:
×
NEW
47
        multiplicand = self._multiplicand()
×
NEW
48
        while True:
×
NEW
49
            if self._accept(_petok.Tokens.TIMES):
×
NEW
50
                next_multiplicand = self._multiplicand()
×
NEW
51
                multiplicand *= next_multiplicand
×
NEW
52
            elif self._accept(_petok.Tokens.DIVIDE):
×
NEW
53
                next_multiplicand = self._multiplicand()
×
NEW
54
                multiplicand /= next_multiplicand
×
55
            else:
NEW
56
                break
×
57

NEW
58
        return multiplicand
×
59

NEW
60
    def _multiplicand(self) -> _exp.Expression:
×
NEW
61
        base = self._power_operand()
×
62

NEW
63
        if not self._accept(_petok.Tokens.POWER):
×
NEW
64
            return base
×
65

NEW
66
        exponent = self._power_operand()
×
67

NEW
68
        return base ** exponent
×
69

NEW
70
    def _power_operand(self) -> _exp.Expression:  # pylint: disable=too-many-return-statements
×
NEW
71
        if positive_integer := self._accept(_petok.Tokens.POSITIVE_INTEGER):
×
NEW
72
            return _exp.Literal(int(positive_integer))
×
73

NEW
74
        if negative_integer := self._accept(_petok.Tokens.NEGATIVE_INTEGER):
×
NEW
75
            return _exp.Literal(int(negative_integer))
×
76

NEW
77
        if number := self._accept(_petok.Tokens.FLOAT):
×
NEW
78
            return _exp.Literal(float(number))
×
79

NEW
80
        if identifier := self._accept(_ptok.Tokens.IDENTIFIER):
×
NEW
81
            if not self._accept(_petok.Tokens.LEFT_PAREN):
×
NEW
82
                return _exp.Variable(identifier)
×
83

NEW
84
            arguments = self._argument_list()
×
NEW
85
            self._expect(_petok.Tokens.RIGHT_PAREN)
×
NEW
86
            return _exp.FunctionCall(identifier, arguments)
×
87

NEW
88
        if self._accept(_petok.Tokens.LEFT_SQUARE_BRACKET):
×
NEW
89
            unit_number, output_number = self._unit_and_output_number()
×
NEW
90
            self._expect(_petok.Tokens.RIGHT_SQUARE_BRACKET)
×
NEW
91
            return _exp.UnitOutput(unit_number, output_number)
×
92

NEW
93
        if self._accept(_petok.Tokens.MINUS):
×
NEW
94
            return -self._expression()
×
95

NEW
96
        if self._accept(_petok.Tokens.LEFT_PAREN):
×
NEW
97
            expression = self._expression()
×
NEW
98
            self._expect(_petok.Tokens.RIGHT_PAREN)
×
NEW
99
            return expression
×
100

NEW
101
        self._raise_parsing_error(
×
102
            "Expected number, variable, function call, opening square bracket or "
103
            "opening parenthesis but found {actual_token}"
104
        )
105

NEW
106
    def _argument_list(self) -> _tp.Sequence[_exp.Expression]:
×
NEW
107
        arguments = [self._expression()]
×
NEW
108
        while self._accept(_petok.Tokens.COMMA):
×
NEW
109
            argument = self._expression()
×
NEW
110
            arguments.append(argument)
×
111

NEW
112
        return arguments
×
113

NEW
114
    def _unit_and_output_number(self) -> _tp.Tuple[int, int]:
×
NEW
115
        unit_number = int(self._expect(_petok.Tokens.POSITIVE_INTEGER))
×
NEW
116
        self._check_non_negative(unit_number, "Unit number")
×
117

NEW
118
        self._expect(_petok.Tokens.COMMA)
×
119

NEW
120
        self._expect(_petok.Tokens.POSITIVE_INTEGER)
×
NEW
121
        output_number = int(self._expect(_petok.Tokens.POSITIVE_INTEGER))
×
NEW
122
        self._check_non_negative(output_number, "Output number")
×
123

NEW
124
        return unit_number, output_number
×
125

NEW
126
    def _check_non_negative(self, integer: int, what: str) -> None:
×
NEW
127
        if integer >= 0:
×
NEW
128
            return
×
129

NEW
130
        self._raise_parsing_error(f"{what} numbers must be non-negative.")
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc