Shop OBEX P1 Docs P2 Docs Learn Events
Can someone show me this? — Parallax Forums

Can someone show me this?

Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
edited 2007-09-19 19:58 in Propeller 1
Now that I've got a handle on storing information from the keyboard, I'm attempting to figure out ways to manipulate it.

for Instance, if I store "type filename" into @command can someone show me how to strip the "type " off leaving
only the "filename" in @command?

It looks like I've got to dump everything after the space to get this right, but I haven't cracked it.

Thanks
Oldbitcollector

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.

— Calvin, of 'Calvin and Hobbes.

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2007-09-19 04:31
    Just for fun ... Here's an input match routine that you could use to do your keyboard processing. It's currently part of a project using a VMusic2, and is intended for parsing both error messages from the Vinculum and data from a text file from a USB flash drive. It inputs from a serial port, but could be modified to use the keyboard input driver just as easily. The comments pretty well describe what it does. The metacharacter "*" is matched against an arbitrary string and the starting index and length of the matching substrings are stored in a table. The input buffer and substrings are not zero-terminated strings because a zero byte is acceptable as data. The routine follows (because the Attachment Manager is broken with the current Mac Safari browser).
    CON
       Cr       = $0D                       ' New line / Return
       Lf       = $0A                       ' Line feed
       Del      = $7F                       ' Delete
    
       maxLine  = 80                        ' Maximum line / pattern length
       maxTime  = 1000                      ' Maximum time for response
       maxArb   = 8                         ' Maximum number of arbitrary strings
    
       matchArb = $0100                     ' Match arbitrary string
       matchMax = matchArb + maxArb - 1
       matchAny = $01FF                     ' Match any single character   
    
    VAR
       long msTime                          ' Precomputed clkfreq / 1000
       word pattern[noparse][[/noparse]maxLine]                ' Work area for pattern match pattern
       byte line[noparse][[/noparse]maxLine]                   ' Input line buffer
       byte lineLen                         ' Current length of input line buffer
       byte patternLen                      ' Current length of pattern
       byte arbPtr[noparse][[/noparse]maxArb]                  ' Arbitrary string - pointer to buffer
       byte arbLen[noparse][[/noparse]maxArb]                  ' Arbitrary string - length of substring
       byte arbPos[noparse][[/noparse]maxArb]                  ' Arbitrary string - position in pattern
       byte arbCnt                          ' Number of arbitrary strings in pattern
    
    OBJ
       ser : "FullDuplexSerial"
    
    PUB start(TxD,RxD)
       msTime := clkfreq / 1000             ' Precompute system clocks per ms
       clearLine                            ' Initialize input line buffer
       ser.start(TxD,RxD,%0000,9600)        ' Start the serial port
    
    PRI clearLine                           ' Clear input line
       lineLen := 0
    
    PRI match(str,ptr,lenPtr,maxLen) | p, i, t, s, c, len, arb
    '' This routine matches the input line against a pattern supplied as a string.
    '' The pattern consists of characters and the metacharacters "*" and "?".
    '' The "\" character is an escape and the next byte is taken literally.
    '' Special cases include "\0" for a zero byte, "\r" for a carriage return,
    '' "\n" for a Unix newline (line feed), and "\d" for delete ($7F).
    '' "?" will match any single byte value.  "*" will match any arbitrary string.
    '' These matches are recorded in arbPtr and arbLen as index and length of the
    '' matched substring in the input.  This routine returns true if successful
    '' and false if there's no match.  The match algorithm works by extending the
    '' last "*" to the first substring that produces a match.  If the input line
    '' is not long enough for the match, this routine attempts to read additional
    '' characters from the serial (FullDuplexSerial) driver with a total timeout
    '' defined by the constant maxTime.
    '' str is the address of the pattern, a zero terminated string.
    '' ptr is the address of the input line buffer
    '' lenPtr is the address of a byte containing the length of the input line
    '' maxLen is the allocated size of the input line buffer
       patternLen := 0                      ' Anchor on left to start of line
       arbCnt := 0
       repeat                               ' Go through pattern string
          case p := byte[noparse][[/noparse]str++]
             0: quit                        ' End of pattern string
             "*":                           ' Match arbitrary string
                arbLen[noparse][[/noparse]arbCnt] := 0
                arbPos[noparse][[/noparse]arbCnt] := patternLen
                pattern[noparse][[/noparse]patternLen++] := matchArb + arbCnt++
             "\":                           ' Escape any byte value
                case p := byte[noparse][[/noparse]str++]
                   0:   quit                ' Ignore if at end of pattern
                   "0": p := 0              ' Substitute a zero byte
                   "r": p := Cr             ' Substitute a return character
                   "n": p := Lf             ' Substitute a line feed character
                   "d": p := Del            ' Substitute a delete character
                pattern[noparse][[/noparse]patternLen++] := p
             "?":                           ' Match any single character
                pattern[noparse][[/noparse]patternLen++] := matchAny
             other:                         ' Any other, take literally
                pattern[noparse][[/noparse]patternLen++] := p
       p := 0
       i := 0
       arb := -1
       len := byte[noparse][[/noparse]lenPtr]
       t := cnt
       repeat                               ' Go back and forth through pattern
          if p == patternLen
             if i == len                    ' At end of pattern, have we matched
                return true                 '  the whole input line?
             if arb < 0                     ' Can we extend the last arbitrary
                return false                '  string to get a complete match?
             p := arbPos[noparse][[/noparse]arb]
             i := arbPtr[noparse][[/noparse]arb]
             arbLen[noparse][[/noparse]arb]++
          case s := pattern[noparse][[/noparse]p++]
             matchArb..matchMax:            ' Going forward through arbitrary
                arb := s - matchArb         '  string, just skip over text
                arbPtr[noparse][[/noparse]arb] := i
                i += arbLen[noparse][[/noparse]arb]
             matchAny:                      ' Going forward through arbitrary
                if i++ == len               '  single character.  Check length
                   if len == maxLen
                      return false
                   repeat while (c := ser.rxcheck) < 0
                      if (cnt - t) => msTime * maxTime
                         return false
                   byte[noparse][[/noparse]lenPtr]++           ' Increment text buffer size
                   byte[noparse][[/noparse]ptr][noparse][[/noparse]len++] := c    '  and save the character
             other:                         ' Going forward through a literal
                if i == len                 '  character, check max length
                   if len == maxLen
                      return false
                   repeat while (c := ser.rxcheck) < 0
                      if (cnt - t) => msTime * maxTime
                         return false
                   byte[noparse][[/noparse]lenPtr]++           ' Increment text buffer size
                   byte[noparse][[/noparse]ptr][noparse][[/noparse]len++] := c    '  and save the character
                if s <> byte[noparse][[/noparse]ptr][noparse][[/noparse]i++]      '   then check for a match
                   if arb < 0               ' See if we can extend the previous
                      return false          '  arbitrary string to get a match
                   p := arbPos[noparse][[/noparse]arb]         ' Extend current arbitrary string
                   i := arbPtr[noparse][[/noparse]arb]         '  and try to match again
                   arbLen[noparse][[/noparse]arb]++
    
    
  • deSilvadeSilva Posts: 2,967
    edited 2007-09-19 05:34
    @Bitcollector: It might be a good idea to look through the appropriate C-libraries, as the techniques used in C are very close to the algorithmic needs of SPIN
  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2007-09-19 14:44
    Mike: Wow... It could take me a another month to digest how that routine works..

    Desilva: Yes, I'm starting to see the similarities to C in spin. That's practical advice.

    Actually, I'm pretty close to a working solution. If I use @buffer[noparse][[/noparse]#] I could grab each
    character of the part I need since I know where the starting position is in each command.
    Not a pretty solution, but one I can understand at the level I'm at.

    Now that I've gotten my mind wrapped around some of the concepts of byte,and case
    (which kept going right over my head initially) The section in the manual for .spin
    commands is starting to make sense. There is a real gap that has to be crossed for
    someone like myself with limited experience in object-oriented programming.

    One of the walls I ran into early with the Propeller is that there is an assumption
    of experience in with other micros when starting with the Propeller, a wall
    I've been chipping away 'hardware-wise' with the Cookbook.

    I'm still building the foundation for a text called ".spin for BASIC programmers"
    Perhaps I can bridge this learning gap for others.

    Oldbitcollector

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.

    — Calvin, of 'Calvin and Hobbes.
  • BergamotBergamot Posts: 185
    edited 2007-09-19 15:02
    I'm surprised that Mike Green didn't implement a full regular expression parser smilewinkgrin.gif
  • MightorMightor Posts: 338
    edited 2007-09-19 19:26
    Bergamot said...
    I'm surprised that Mike Green didn't implement a full regular expression parser smilewinkgrin.gif
    He's working on that for the next post, just wait...

    Mike, how's the flux_capacitor.spin program coming along?

    Gr,
    Mightor

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    | To know recursion, you must first know recursion.
    | I reject your reality and substitute my own!
    | - Adam Savage
  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2007-09-19 19:53
    He must still be working on the time_space.spin dependency..

    [noparse];)[/noparse]

    Oldbitcollector

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.

    — Calvin, of 'Calvin and Hobbes.
  • mcstarmcstar Posts: 144
    edited 2007-09-19 19:58
    Thanks for the post Mike! Truly,truly I was just thinking about how to go about writing a parser (to handle the vinculum responses) myself. This will give me a great start. The next parser I'm thinking about is one for propositional logic. Perhaps I can work on that one next now.
    BTW, my vinculum host responses are already in stuffed into a LockPool, so I'll be modifying Mike's code to work from there. If anyone else wants a version that reads from a memory pool stay tuned and I'll post the code here.
Sign In or Register to comment.