HEX
Server: Apache/2.4.65 (Ubuntu)
System: Linux ielts-store-v2 6.8.0-1036-gcp #38~22.04.1-Ubuntu SMP Thu Aug 14 01:19:18 UTC 2025 x86_64
User: root (0)
PHP: 7.2.34-54+ubuntu20.04.1+deb.sury.org+1
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
Upload Files
File: //snap/google-cloud-cli/394/platform/gsutil/third_party/pyparsing/examples/one_to_ninety_nine.py
#
# 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")

# for expressions that parse multiple values, add them up
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)