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

vinci1it2000 / formulas / 17749796115

15 Sep 2025 11:32PM UTC coverage: 98.254% (-0.3%) from 98.588%
17749796115

push

github

vinci1it2000
chore(ver): bump 1.3.0 --> 1.3.1.

2 of 2 new or added lines in 1 file covered. (100.0%)

80 existing lines in 12 files now uncovered.

5682 of 5783 relevant lines covered (98.25%)

0.98 hits per line

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

97.83
/formulas/parser.py
1
#!/usr/bin/env python
2
# -*- coding: UTF-8 -*-
3
#
4
# Copyright 2016-2025 European Commission (JRC);
5
# Licensed under the EUPL (the 'Licence');
6
# You may not use this work except in compliance with the Licence.
7
# You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
8

9
"""
10
It provides formula parser class.
11
"""
12

13
# noinspection PyCompatibility
14
import regex
1✔
15
from .errors import TokenError, FormulaError, ParenthesesError
1✔
16
from .tokens.operand import String, Error, Number, Range
1✔
17
from .tokens.operator import OperatorToken, Separator, Intersect
1✔
18
from .tokens.function import Function, Array, Lambda
1✔
19
from .tokens.parenthesis import Parenthesis
1✔
20
from .builder import AstBuilder
1✔
21

22

23
class Parser:
1✔
24
    formula_check = regex.compile(
1✔
25
        r"""
26
        (?P<array>^\s*{\s*=\s*(?P<name>\S.*)\s*}\s*$)
27
        |
28
        (?P<value>^\s*=\s*(?P<name>\S.*))
29
        """, regex.IGNORECASE | regex.X | regex.DOTALL
30
    )
31
    ast_builder = AstBuilder
1✔
32
    filters = [
1✔
33
        Error, String, Number, Lambda, Range, OperatorToken, Separator,
34
        Function, Array, Parenthesis, Intersect
35
    ]
36

37
    def __init__(self, is_cell=False):
1✔
38
        self.is_cell = is_cell
1✔
39

40
    def is_formula(self, value):
1✔
41
        return self.formula_check.match(value) or Error._re.match(value)
1✔
42

43
    def ast(self, expression, context=None):
1✔
44
        try:
1✔
45
            match = self.is_formula(expression.replace('\n', '')).groupdict()
1✔
46
            expr = match['name']
1✔
47
        except (AttributeError, KeyError):
1✔
48
            raise FormulaError(expression)
1✔
49
        builder = self.ast_builder(match=match)
1✔
50
        filters, tokens, stack = self.filters, [], []
1✔
51
        Parenthesis('(').ast(tokens, stack, builder)
1✔
52
        while expr:
1✔
53
            for f in filters:
1✔
54
                try:
1✔
55
                    token = f(expr, context, self)
1✔
56
                    token.ast(tokens, stack, builder)
1✔
57
                    expr = expr[token.end_match:]
1✔
58
                    break
1✔
59
                except TokenError:
1✔
60
                    pass
1✔
61
                except FormulaError:
1✔
62
                    raise FormulaError(expression)
1✔
63
            else:
64
                raise FormulaError(expression)
1✔
65
        Parenthesis(')').ast(tokens, stack, builder)
1✔
66
        tokens = tokens[1:-1]
1✔
67
        while stack:
1✔
68
            if isinstance(stack[-1], Parenthesis):
1✔
69
                raise ParenthesesError()
1✔
70
            builder.append(stack.pop())
1✔
71
        if len(builder) != 1:
1✔
UNCOV
72
            raise FormulaError(expression)
×
73
        builder.finish()
1✔
74
        return tokens, builder
1✔
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