summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/one_to_ninety_nine.py72
1 files changed, 72 insertions, 0 deletions
diff --git a/examples/one_to_ninety_nine.py b/examples/one_to_ninety_nine.py
new file mode 100644
index 0000000..6f5520f
--- /dev/null
+++ b/examples/one_to_ninety_nine.py
@@ -0,0 +1,72 @@
+#
+# one_to_ninety_nine.py
+#
+# Copyright 2021, Paul McGuire
+#
+# Parser/evaluator for expressions of numbers as written out in words:
+# - one
+# - seven
+# - twelve
+# - twenty six
+# - forty-two
+#
+# BNF:
+# units ::= one | two | three | ... | nine
+# teens ::= ten | eleven | twelve | ... | nineteen
+# tens ::= twenty | thirty | ... | ninety
+# one_to_99 ::= units | teens | (tens [["-"] units])
+#
+import pyparsing as pp
+
+
+def define_numeric_word_range(
+ names: str,
+ from_: int,
+ to_: int,
+ step: int = 1) -> pp.MatchFirst:
+ """
+ Compose a MatchFirst of CaselessKeywords, given their names and values,
+ which when parsed, are converted to their value
+ """
+
+ def define_numeric_word(nm: str, val: int):
+ return pp.CaselessKeyword(nm).add_parse_action(lambda: val)
+
+ names = names.split()
+ values = range(from_, to_ + 1, step)
+ return pp.MatchFirst(
+ define_numeric_word(name, value) for name, value in zip(names, values)
+ )
+
+
+units = define_numeric_word_range(
+ "one two three four five six seven eight nine", 1, 9
+).set_name("units")
+teens = define_numeric_word_range(
+ "ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen", 10, 19
+).set_name("teens")
+tens = define_numeric_word_range(
+ "twenty thirty forty fifty sixty seventy eighty ninety", 20, 90, step=10
+).set_name("tens")
+
+opt_dash = pp.Opt(pp.Suppress("-"))
+twenty_to_99 = tens + pp.Opt(opt_dash + units)
+
+one_to_99 = (units | teens | twenty_to_99).set_name("1-99")
+one_to_99.add_parse_action(sum)
+
+numeric_expression = one_to_99
+
+if __name__ == "__main__":
+ numeric_expression.run_tests(
+ """
+ one
+ seven
+ twelve
+ twenty six
+ forty-two
+ """
+ )
+
+ # create railroad diagram
+ numeric_expression.create_diagram("one_to_99_diagram.html", vertical=5)