Original Parser

version 1 by Ron Newcomb

  • Home page
  • Beginning
  • Previous
  • Next



  • Chapter - TryNumber

    [|TryNumber| takes word number |wordnum| and tries to parse it as an (unsigned)
    decimal number or the name of a small number, returning

    (a) $-1000$ if it is not a number
    (b) the number, if it has between 1 and 4 digits
    (c) 10000 if it has 5 or more digits.

    (The danger of allowing 5 digits is that Z-machine integers are only 16 bits
    long, and anyway this routine isn't meant to be perfect: it only really needs
    to be good enough to handle numeric descriptors such as those in TAKE 31 COINS
    or DROP FOUR DAGGERS. In particular, it is not the way I7 ``[number]'' tokens
    are parsed.)]

    To decide what number is the number typed in by the player at (Nth - a number) (this is TryNumber):
        save the parser's current word position;
        now the parser's current word position is the Nth;
        let the num be the next word as digits; [ is it a word like "twenty"? ]
        restore the parser's current word position;
        if the num is at least 1, decide on the num;
        now num is 0; [ otherwise it's in numeric form like "365", so read them a 'letter' at a time, toting them up. ]
        let the typed number be the player's input buffer advanced to the Nth word's position of the player's parsed command - 1;
        repeat with ith running from 1 to the Nth word's length of the player's parsed command:
            let the digit's value be the ith letter of the typed number as a numeric digit;
            if the digit's value < 0 or the digit's value > 9, [ then it isn't a numeric digit, so ] decide on -1000;
            if num >= 1000, [then we're about to make a five-digit number, a total >= 10,000, so cap it: ] decide on 10000;
            now num is (num multiplied by 10) plus the digit's value;
        decide on the num.


    [ TryNumber wordnum i j c num len mul tot d digit;
    i = wn; wn = wordnum; j = NextWord(); wn = i;
    j = NumberWord(j); ! Test for verbal forms ONE to THIRTY
    if (j >= 1) return j;

    #Ifdef TARGET_ZCODE;
    i = wordnum*4+1; j = parse->i; num = j+buffer; len = parse->(i-1);
    #Ifnot; ! TARGET_GLULX
    i = wordnum*3; j = parse-->i; num = j+buffer; len = parse-->(i-1);
    #Endif; ! TARGET_

    if (len >= 4) mul=1000;
    if (len == 3) mul=100;
    if (len == 2) mul=10;
    if (len == 1) mul=1;

    tot = 0; c = 0; len = len-1;

    for (c=0 : c<=len : c++) {
    digit=num->c;
    if (digit == '0') { d = 0; jump digok; }
    if (digit == '1') { d = 1; jump digok; }
    if (digit == '2') { d = 2; jump digok; }
    if (digit == '3') { d = 3; jump digok; }
    if (digit == '4') { d = 4; jump digok; }
    if (digit == '5') { d = 5; jump digok; }
    if (digit == '6') { d = 6; jump digok; }
    if (digit == '7') { d = 7; jump digok; }
    if (digit == '8') { d = 8; jump digok; }
    if (digit == '9') { d = 9; jump digok; }
    return -1000;
    .digok;
    tot = tot+mul*d; mul = mul/10;
    }
    if (len > 3) tot=10000;
    return tot;
    ]