summaryrefslogtreecommitdiff
path: root/examples/excel_expr.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/excel_expr.py')
-rw-r--r--examples/excel_expr.py93
1 files changed, 93 insertions, 0 deletions
diff --git a/examples/excel_expr.py b/examples/excel_expr.py
new file mode 100644
index 0000000..db19f3c
--- /dev/null
+++ b/examples/excel_expr.py
@@ -0,0 +1,93 @@
+# excelExpr.py
+#
+# Copyright 2010, Paul McGuire
+#
+# A partial implementation of a parser of Excel formula expressions.
+#
+import pyparsing as pp
+ppc = pp.common
+
+pp.ParserElement.enablePackrat()
+
+EQ, LPAR, RPAR, COLON, COMMA = pp.Suppress.using_each("=():,")
+EXCL, DOLLAR = pp.Literal.using_each("!$")
+sheetRef = pp.Word(pp.alphas, pp.alphanums) | pp.QuotedString("'", escQuote="''")
+colRef = pp.Opt(DOLLAR) + pp.Word(pp.alphas, max=2)
+rowRef = pp.Opt(DOLLAR) + pp.Word(pp.nums)
+cellRef = pp.Combine(
+ pp.Group(pp.Opt(sheetRef + EXCL)("sheet") + colRef("col") + rowRef("row"))
+)
+
+cellRange = (
+ pp.Group(cellRef("start") + COLON + cellRef("end"))("range")
+ | cellRef
+ | pp.Word(pp.alphas, pp.alphanums)
+)
+
+expr = pp.Forward()
+
+COMPARISON_OP = pp.one_of("< = > >= <= != <>")
+condExpr = expr + COMPARISON_OP + expr
+
+ifFunc = (
+ pp.CaselessKeyword("if")
+ - LPAR
+ + pp.Group(condExpr)("condition")
+ + COMMA
+ + pp.Group(expr)("if_true")
+ + COMMA
+ + pp.Group(expr)("if_false")
+ + RPAR
+)
+
+
+def stat_function(name):
+ return pp.Group(pp.CaselessKeyword(name) + pp.Group(LPAR + pp.DelimitedList(expr) + RPAR))
+
+
+sumFunc = stat_function("sum")
+minFunc = stat_function("min")
+maxFunc = stat_function("max")
+aveFunc = stat_function("ave")
+funcCall = ifFunc | sumFunc | minFunc | maxFunc | aveFunc
+
+multOp = pp.one_of("* /")
+addOp = pp.one_of("+ -")
+numericLiteral = ppc.number
+operand = numericLiteral | funcCall | cellRange | cellRef
+arithExpr = pp.infix_notation(
+ operand,
+ [
+ (multOp, 2, pp.OpAssoc.LEFT),
+ (addOp, 2, pp.OpAssoc.LEFT),
+ ],
+)
+
+textOperand = pp.dblQuotedString | cellRef
+textExpr = pp.infix_notation(
+ textOperand,
+ [
+ ("&", 2, pp.OpAssoc.LEFT),
+ ],
+)
+
+expr <<= arithExpr | textExpr
+
+
+def main():
+ success, report = (EQ + expr).run_tests(
+ """\
+ =3*A7+5
+ =3*Sheet1!$A$7+5
+ =3*'Sheet 1'!$A$7+5
+ =3*'O''Reilly''s sheet'!$A$7+5
+ =if(Sum(A1:A25)>42,Min(B1:B25),if(Sum(C1:C25)>3.14, (Min(C1:C25)+3)*18,Max(B1:B25)))
+ =sum(a1:a25,10,min(b1,c2,d3))
+ =if("T"&a2="TTime", "Ready", "Not ready")
+ """
+ )
+ assert success
+
+
+if __name__ == '__main__':
+ main() \ No newline at end of file