Help parsin numbers

Anonymous
2012-02-01
2013-05-14
  • Anonymous

    Anonymous - 2012-02-01

    Good morning,
    I'm trying to parse numbers, both in decimal and hexadecimal format, and I need to return their radix.
    My problem is that the ParseResults objects passed to my parseAction does nto have the attribute hex or dec as i specify.
    Here is my code:

    def processParsedNum(results):
        '''
        Process a ParsingResults objects resulting from parsing a number
        @param results: the object containing all the parsed tokens
        @return a stringified version of the parsed number
        '''
        #Process value
        val = results.value
        radix = 10
        rawValue = results.value
        #Process radix
        strValue = None
        if results.dec:
            strValue = val.dec
        elif results.hex:
            strValue = "0x" + val.hex
            results = 16
        #Process prefix
        if results.prefix:
            strValue = results.prefix + strValue
        results = strValue
        results = radix
        results = rawValue
        return results

    #Decimal numbers
    SYMBOL = oneOf('+ -')
    NUM_INT = Word(nums)
    NUM_FLOAT = Combine(NUM_INT + Literal(".") + NUM_INT, adjacent=True)
    NUM_EXPONENTIAL = Combine(Or() + \
                              oneOf("E e") + \
                              Optional(SYMBOL) + \
                              NUM_INT, \
                              adjacent=True)
    NUM_DEC = Or()
    NUM_DEC.setResultsName('dec')

    #HEXADECIMAL number may have either the prefix . or the h,H suffixes
    NUM_HEX = Or([Suppress(Literal(".")) + Word(nums+"ABCDEF"+"abcdef"), \
                  Word(nums+"ABCDEF"+"abcdef") + Suppress(oneOf("H h"))])
    NUM_HEX.setResultsName('hex')

    NUM = Optional(SYMBOL).setResultsName('prefix') + \
          Or().setResultsName('value')
    NUM
    NUM.setParseAction(processParsedNum)

    I don't know what i'm doing wrong (of course i'm doing something), but i guess there should be a way of navigating through the parsed elements and it sub-elements.

    Thanks in advance.

    Cheers!

     
  • Paul McGuire

    Paul McGuire - 2012-06-16

    Sorry to not see your post earlier. The problem is in the somewhat misleading function name "setResultsName". This method does not just set the return name, but returns a copy of the original expression. The reason for this is that a single expression might occur several times in a larger parser, with different results names associated with it.

    In your parser, the solution is to simply assign the value returned by setResultsName back to the expression itself:

    NUM_DEC = NUM_DEC.setResultsName('dec')
    NUM_HEX = NUM_HEX.setResultsName('hex')
    

    There is a shortened form of setResultsName which is useful when building up a larger expression from smaller ones.

    NUM_DEC = NUM_DEC('dec')
    NUM_HEX = NUM_HEX('hex')
    

    Otherwise, your pyparsing parser code looks fine. With these changes, I was able to get your parser working with test strings "100", ".100", and "100h".  You have a few remaining minor bugs in your parse action, here is a working version:

    def processParsedNum(results):
        '''
        Process a ParsingResults objects resulting from parsing a number
        @param results: the object containing all the parsed tokens 
        @return a stringified version of the parsed number
        '''
        #Process value
        val = results.value
        radix = 10
        rawValue = results.value
        #Process radix
        strValue = None
        if results.dec:
            strValue = results.dec
        elif results.hex:
            strValue = "0x" + results.hex
            radix = 16
        #Process prefix
        if results.prefix:
            strValue = results.prefix + strValue
        results['value'] = strValue
        results['radix'] = radix
        results['rawValue'] = rawValue
        return results
    

    Sorry for the delay, good luck in your parsing endeavors!
    - Paul McGuire

     

Log in to post a comment.