Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.unix.shell > #26531

Re: handy shell function/alias that wraps bc

From ram@zedat.fu-berlin.de (Stefan Ram)
Newsgroups comp.unix.shell
Subject Re: handy shell function/alias that wraps bc
Date 2025-10-31 18:21 +0000
Organization Stefan Ram
Message-ID <parser-20251031191650@ram.dialup.fu-berlin.de> (permalink)
References <10e1l5i$8scp$1@dont-email.me>

Show all headers | View raw


Michael Sanders <porkchop@invalid.foo> wrote or quoted:
># test cases: expression|expected output

  Oh man, that takes me back to my old parsers. I just tried
  writing one for Bash. It's really just a bare-bones demo though - 
  everything's integers, the numbers can only have a single digit, and
  the power operator only works if both sides are between 0 and 11.

#!/bin/bash

g=""
pos=0
REPLY="" # Used as a global return variable

# xpow: only for args between 0 and 11
xpow() {
  local x=$1 y=$2 result=1 i
  if [ "$x" -lt 11 ] && [ "$y" -lt 11 ]; then
    for i in $(seq 1 $y); do
      result=$((result * x))
    done
    echo "$result"
  fi
}

xmul() {
  echo $(($1 * $2))
}

xdiv() {
  echo $(($1 / $2))
}

xadd() {
  echo $(($1 + $2))
}

xsub() {
  echo $(($1 - $2))
}

declare -A op_func op_left

op_func["^"]="xpow"; op_left["^"]=0 # right associative
op_func["*"]="xmul"; op_left["*"]=1 # left associative
op_func["/"]="xdiv"; op_left["/"]=1
op_func["+"]="xadd"; op_left["+"]=1
op_func["-"]="xsub"; op_left["-"]=1

lookup() {
  local name=$1
  if [[ -n ${op_func[$name]} ]]; then
    echo "$name ${op_func[$name]} ${op_left[$name]}"
  else
    echo "0 0 0"
  fi
}

peek() {
  REPLY="${g:pos:1}"
}

get() {
  REPLY="${g:pos:1}"
  if [[ -n "$REPLY" ]]; then
    pos=$((pos + 1))
  fi
}

check() {
  local op_chars="$1"
  peek
  local ch="$REPLY"
  if [[ "$op_chars" == *"$ch"* ]]; then
    get
  else
    REPLY=""
  fi
}

numeral() {
  local ch
  get
  ch="$REPLY"
  REPLY=$((10#$ch - 0))
}

prefix() {
  local sign=1
  peek
  while [[ "$REPLY" == "-" ]]; do
    get
    sign=$((sign * -1))
    peek
  done
  numeral
  REPLY=$((sign * REPLY))
}

parse() {
  local op_chars="$1" # $1: op_chars (e.g., "+-")
  local next_func="$2" # $2: next_func (e.g., "product")
  local result

  $next_func
  result="$REPLY"

  while true; do
    local sym
    check "$op_chars"
    sym="$REPLY"

    [[ -z "$sym" ]] && break

    local _name func left_assoc
    read -r _name func left_assoc <<<"$(lookup "$sym")"

    local ll=$left_assoc

    local x
    if [[ "$ll" -eq 1 ]]; then
      $next_func
      x="$REPLY"
    else
      parse "$op_chars" "$next_func"
      x="$REPLY"
    fi

    result=$($func "$result" "$x")
  done

  REPLY="$result"
}

power() {
  parse "^" prefix
}

product() {
  parse "*/" power
}

sum() {
  parse "+-" product
}

start() {
  sum
}

test_expr() {
    local s="$1"
    g="$s"
    pos=0
    start
    printf "Test '%s' Result: %g\n" "$s" "$REPLY"
}

test_expr "-2"
test_expr "--2"
test_expr "-2*-2"
test_expr "2^3^2"
test_expr "2*2^3^2-1"
test_expr "1+2^3^2/2"

Back to comp.unix.shell | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

handy shell function/alias that wraps bc Michael Sanders <porkchop@invalid.foo> - 2025-10-31 06:32 +0000
  Re: handy shell function/alias that wraps bc Lawrence D’Oliveiro <ldo@nz.invalid> - 2025-10-31 06:38 +0000
    Re: handy shell function/alias that wraps bc gazelle@shell.xmission.com (Kenny McCormack) - 2025-10-31 10:16 +0000
      Re: handy shell function/alias that wraps bc Michael Sanders <porkchop@invalid.foo> - 2025-10-31 15:49 +0000
    Re: handy shell function/alias that wraps bc Geoff Clare <geoff@clare.See-My-Signature.invalid> - 2025-10-31 13:16 +0000
      Re: handy shell function/alias that wraps bc Lawrence D’Oliveiro <ldo@nz.invalid> - 2025-10-31 23:29 +0000
    Re: handy shell function/alias that wraps bc Michael Sanders <porkchop@invalid.foo> - 2025-10-31 15:31 +0000
    Re: handy shell function/alias that wraps bc Jim <zsd+ng@jdvb.ca> - 2025-11-07 10:09 -0400
      Re: handy shell function/alias that wraps bc Lawrence D’Oliveiro <ldo@nz.invalid> - 2025-11-08 00:00 +0000
        Re: handy shell function/alias that wraps bc Christian Weisgerber <naddy@mips.inka.de> - 2025-11-08 16:51 +0000
          Re: handy shell function/alias that wraps bc Lawrence D’Oliveiro <ldo@nz.invalid> - 2025-11-08 21:55 +0000
        Re: handy shell function/alias that wraps bc Jim Diamond <zsd@jdvb.ca> - 2025-11-19 20:37 -0400
          Re: handy shell function/alias that wraps bc Brian Patrie <bpatrie@bellsouth.spamisicky.net> - 2025-11-23 14:40 -0600
            Re: handy shell function/alias that wraps bc Lawrence D’Oliveiro <ldo@nz.invalid> - 2025-11-23 20:58 +0000
            Re: handy shell function/alias that wraps bc Jim Diamond <zsd@jdvb.ca> - 2025-11-24 21:12 -0400
  Re: handy shell function/alias that wraps bc Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-10-31 10:38 +0100
    Re: handy shell function/alias that wraps bc gazelle@shell.xmission.com (Kenny McCormack) - 2025-10-31 12:39 +0000
      Re: handy shell function/alias that wraps bc Kaz Kylheku <643-408-1753@kylheku.com> - 2025-10-31 17:03 +0000
      Re: handy shell function/alias that wraps bc Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-10-31 18:14 +0100
        Re: handy shell function/alias that wraps bc Richard Harnden <richard.nospam@gmail.invalid> - 2025-11-03 14:03 +0000
          Re: handy shell function/alias that wraps bc Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-03 15:10 +0100
            Re: handy shell function/alias that wraps bc Richard Harnden <richard.nospam@gmail.invalid> - 2025-11-03 14:40 +0000
              Re: handy shell function/alias that wraps bc gazelle@shell.xmission.com (Kenny McCormack) - 2025-11-03 16:11 +0000
                Re: handy shell function/alias that wraps bc Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-03 17:24 +0100
                Re: handy shell function/alias that wraps bc gazelle@shell.xmission.com (Kenny McCormack) - 2025-11-03 17:33 +0000
                Re: handy shell function/alias that wraps bc Christian Weisgerber <naddy@mips.inka.de> - 2025-11-03 23:19 +0000
                Re: handy shell function/alias that wraps bc Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-04 05:34 +0100
                Re: handy shell function/alias that wraps bc Kaz Kylheku <643-408-1753@kylheku.com> - 2025-11-04 04:40 +0000
                Re: handy shell function/alias that wraps bc Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-04 05:57 +0100
                Re: handy shell function/alias that wraps bc Kaz Kylheku <643-408-1753@kylheku.com> - 2025-11-04 00:35 +0000
                Re: handy shell function/alias that wraps bc Kaz Kylheku <643-408-1753@kylheku.com> - 2025-11-04 01:04 +0000
            Re: handy shell function/alias that wraps bc Christian Weisgerber <naddy@mips.inka.de> - 2025-11-03 15:56 +0000
          Re: handy shell function/alias that wraps bc Lawrence D’Oliveiro <ldo@nz.invalid> - 2025-11-03 20:06 +0000
            Re: handy shell function/alias that wraps bc Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-11-03 21:25 +0100
            Re: handy shell function/alias that wraps bc Kaz Kylheku <643-408-1753@kylheku.com> - 2025-11-03 21:11 +0000
    Re: handy shell function/alias that wraps bc Michael Sanders <porkchop@invalid.foo> - 2025-10-31 15:53 +0000
  Re: handy shell function/alias that wraps bc Christian Weisgerber <naddy@mips.inka.de> - 2025-10-31 14:56 +0000
    Re: handy shell function/alias that wraps bc Michael Sanders <porkchop@invalid.foo> - 2025-10-31 15:54 +0000
      Re: handy shell function/alias that wraps bc Nuno Silva <nunojsilva@invalid.invalid> - 2025-11-01 10:43 +0000
        Re: handy shell function/alias that wraps bc Michael Sanders <porkchop@invalid.foo> - 2025-11-01 12:29 +0000
  Re: handy shell function/alias that wraps bc Michael Sanders <porkchop@invalid.foo> - 2025-10-31 17:51 +0000
  Re: handy shell function/alias that wraps bc ram@zedat.fu-berlin.de (Stefan Ram) - 2025-10-31 18:21 +0000
    Re: handy shell function/alias that wraps bc Michael Sanders <porkchop@invalid.foo> - 2025-10-31 19:15 +0000
  Re: handy shell function/alias that wraps bc Ed Morton <mortonspam@gmail.com> - 2025-11-01 11:47 -0500
    Re: handy shell function/alias that wraps bc Lawrence D’Oliveiro <ldo@nz.invalid> - 2025-11-01 20:21 +0000
      Other languages and people's personal issues (Was: handy shell function/alias that wraps bc) gazelle@shell.xmission.com (Kenny McCormack) - 2025-11-01 21:27 +0000
      Re: handy shell function/alias that wraps bc Ed Morton <mortonspam@gmail.com> - 2025-11-02 16:58 -0600
        Re: handy shell function/alias that wraps bc Lawrence D’Oliveiro <ldo@nz.invalid> - 2025-11-03 01:53 +0000
          Re: handy shell function/alias that wraps bc gazelle@shell.xmission.com (Kenny McCormack) - 2025-11-03 02:39 +0000
          Re: handy shell function/alias that wraps bc Ed Morton <mortonspam@gmail.com> - 2025-11-04 16:49 -0600
            Re: handy shell function/alias that wraps bc Lawrence D’Oliveiro <ldo@nz.invalid> - 2025-11-05 00:06 +0000
          Re: handy shell function/alias that wraps bc Kaz Kylheku <643-408-1753@kylheku.com> - 2025-11-04 23:06 +0000

csiph-web