spreadsheet

terminal spreadsheet application
git clone https://git.ce9e.org/spreadsheet.git

commit
d945d21dd639aa6b4bfb382d4d5e7598ce45dfe9
parent
61f967c8272d9e27bcf1b37e2713f7800d2baa27
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-07-06 17:29
expressions: unparse

Diffstat

M sheet/expression.py 49 ++++++++++++++++++++++++++++++++++++++++---------
M sheet/sheet.py 4 +++-

2 files changed, 43 insertions, 10 deletions


diff --git a/sheet/expression.py b/sheet/expression.py

@@ -24,17 +24,17 @@ def parse_re(text, pattern):
   24    24 
   25    25 def parse_string(text):
   26    26     m, tail = parse_re(text, r'"[^"]*"')
   27    -1     return ('str', m[0][1:-1]), tail
   -1    27     return ('str', m[0][1:-1], m[0]), tail
   28    28 
   29    29 
   30    30 def parse_float(text):
   31    31     m, tail = parse_re(text, r'[0-9]+\.[0-9]+')
   32    -1     return ('float', float(m[0])), tail
   -1    32     return ('float', float(m[0]), m[0]), tail
   33    33 
   34    34 
   35    35 def parse_int(text):
   36    36     m, tail = parse_re(text, r'[0-9]+')
   37    -1     return ('int', int(m[0], 10)), tail
   -1    37     return ('int', int(m[0], 10), m[0]), tail
   38    38 
   39    39 
   40    40 def col2x(col):
@@ -74,21 +74,23 @@ def parse_brace(text):
   74    74     _, tail = parse_re(text, r'\(')
   75    75     exp, tail = parse_expression(tail)
   76    76     _, tail = parse_re(tail, r'\)')
   77    -1     return exp, tail
   -1    77     return ('brace', exp), tail
   78    78 
   79    79 
   80    80 def parse_call(text):
   81    81     m, tail = parse_re(text, r'[a-zA-Z][a-zA-Z0-9]*')
   82    82     _, tail = parse_re(tail, r'\(')
   83    83     args = []
   -1    84     commas = []
   84    85     if tail.startswith(')'):
   85    -1         return (m[0], args), tail[1:]
   -1    86         return (m[0], args, commas), tail[1:]
   86    87     while True:
   87    88         arg, tail = parse_expression(tail)
   88    89         args.append(arg)
   89    90         if tail.startswith(')'):
   90    -1             return (m[0], args), tail[1:]
   91    -1         _, tail = parse_re(tail, r',\s*')
   -1    91             return (m[0], args, commas), tail[1:]
   -1    92         c, tail = parse_re(tail, r',\s*')
   -1    93         commas.append(c[0])
   92    94     raise ParseError('no closing brace on function call')
   93    95 
   94    96 
@@ -112,7 +114,7 @@ def parse_expression2(text):
  112   114         except ParseError:
  113   115             break
  114   116         rhs, tail = parse_expression3(tail)
  115    -1         lhs = m[0].strip(), lhs, rhs
   -1   117         lhs = m[0].strip(), lhs, rhs, m[0]
  116   118     return lhs, tail
  117   119 
  118   120 
@@ -124,7 +126,7 @@ def parse_expression(text):
  124   126         except ParseError:
  125   127             break
  126   128         rhs, tail = parse_expression2(tail)
  127    -1         lhs = m[0].strip(), lhs, rhs
   -1   129         lhs = m[0].strip(), lhs, rhs, m[0]
  128   130     return lhs, tail
  129   131 
  130   132 
@@ -133,3 +135,32 @@ def parse(text):
  133   135     if tail:
  134   136         raise ParseError(f'unexpected tail: {tail}')
  135   137     return expr
   -1   138 
   -1   139 
   -1   140 def unparse(expr):
   -1   141     if expr[0] in ['str', 'float', 'int']:
   -1   142         return expr[2]
   -1   143     elif expr[0] == 'ref':
   -1   144         s = ''
   -1   145         if expr[2][0]:
   -1   146             s += '$'
   -1   147         s += x2col(expr[1][0])
   -1   148         if expr[2][1]:
   -1   149             s += '$'
   -1   150         s += str(expr[1][1] + 1)
   -1   151         return s
   -1   152     elif expr[0] == 'range':
   -1   153         return unparse(expr[1]) + ':' + unparse(expr[2])
   -1   154     elif expr[0] == 'brace':
   -1   155         return '(' + unparse(expr[1]) + ')'
   -1   156     elif expr[0] in '+-*/':
   -1   157         return unparse(expr[1]) + expr[3] + unparse(expr[2])
   -1   158     else:
   -1   159         name, args, commas = expr
   -1   160         assert len(args) == len(commas) + 1
   -1   161         sargs = ''
   -1   162         if args:
   -1   163             for i, comma in enumerate(commas):
   -1   164                 sargs += unparse(args[i]) + comma
   -1   165             sargs += unparse(args[-1])
   -1   166         return f'{name}({sargs})'

diff --git a/sheet/sheet.py b/sheet/sheet.py

@@ -52,7 +52,7 @@ class Sheet:
   52    52             pass
   53    53         return raw
   54    54 
   55    -1     def call_function(self, name: str, args: list[tuple]) -> float|int|str:
   -1    55     def call_function(self, name: str, args: list[tuple], _commas: list[str]) -> float|int|str:
   56    56         if name == 'sum':
   57    57             if len(args) != 1 or args[0][0] != 'range':
   58    58                 raise ValueError(args)
@@ -75,6 +75,8 @@ class Sheet:
   75    75             return expr[1]
   76    76         elif expr[0] == 'ref':
   77    77             return self.get_value(expr[1])
   -1    78         elif expr[0] == 'brace':
   -1    79             return self.evaluate(expr[1])
   78    80         elif expr[0] == 'err':
   79    81             raise expr[1]
   80    82         elif expr[0] == '+':