|
Answer» Hi everyone , Found out while implementing the Shunting Yard algorithm in VB that functions with argument separators can be used wrong:
This line of pseudo-code for example is accepted by this algorithm but it's not the wright way to use parenthesis right?
functionName((2000,)500)
more info about the algorithm: http://en.wikipedia.org/wiki/Shunting-yard_algorithm
does anyone know a simple way to solve this bug? Thanks in advance TomA lot of views but no reply, Did i say something wrong? or is this question placed in the wrong section of the forum? Going to upload the code anyway for those who maybe are interested.. maybe i did something wrong in the code?
(its in vbscript btw)
Code: [Select]input = split("function ( 1 ( , 2 ) )") msgbox shuntingyard(input)
function shuntingyard(input)
Queue = array() Stack = array() for Counter = 0 to ubound(input) select case input(Counter) case "(" call push(input(Counter), Stack) case ")" do while not(peek(Stack) = "(") if stackisempty(Stack) then MsgBox"can't find a matching ""(""." call push(pop(Stack), Queue) loop discard = pop(Stack) case "+","-","*","/","%","^" operator_a = input(Counter) do while isOperator(peek(Stack)) operator_b = peek(Stack) if (associativity(operator_b) = "left" and precedence(operator_a) = precedence(operator_b)) or (precedence(operator_a) < precedence(operator_b)) then call push(pop(Stack), Queue) else exit do END if loop call push(operator_a, Stack) case "function" call push(input(Counter), Stack) case ","'function seperator 'until the token at the top of the stack is a left parenthesis, 'pop operators off the stack onto the output queue. 'if no left parentheses are encountered, 'either the separator was MISPLACED or parentheses were mismatched. do while not(peek(Stack) = "(") if stackisempty(Stack) then MsgBox"can't find a matching ""("" for a function." call push(pop(Stack), Queue) loop case else'"number" call push(input(Counter), Queue)
end select next for itemcount = 0 to ubound(Stack) if peek(Stack) = "(" then MsgBox"can't find a matching "")""." call push(pop(Stack), Queue) next shuntingyard = join(Queue," ") end function
function isoperator(item) isoperator = len(item) = 1 and instr("+-*/%^",item) end function set precedence = createobject("scripting.dictionary") with precedence .add "^",10'[right] .add "*",8 .add "/",8 .add "%",8 .add "+",7 .add "-",7 end with function associativity(assoc) select case lcase(assoc) case "^","\" associativity = "right" case else associativity = "left" end select end function
SUB PUSH(ITEM,BYREF STACK) IF UBOUND(STACK) > -1 THEN REDIM PRESERVE STACK(UBOUND(STACK) + 1) STACK(UBOUND(STACK)) = ITEM ELSE STACK = ARRAY(ITEM) END IF END SUB FUNCTION POP(STACK) IF UBOUND(STACK) > -1 THEN POP = STACK(UBOUND(STACK)) REDIM PRESERVE STACK(UBOUND(STACK) - 1) END IF END FUNCTION FUNCTION STACKISEMPTY(STACK) IF UBOUND(STACK) > -1 THEN STACKISEMPTY = FALSE ELSE STACKISEMPTY = TRUE END IF END FUNCTION FUNCTION PEEK(STACK) IF UBOUND(STACK) > -1 THEN PEEK = STACK(UBOUND(STACK)) END IF END FUNCTION At the comma it finds a ( immediately so never executes the loop body.
it also throws a subscript out of range error when POP() is called and the array only has ONE item. In this case the exception occurs when only "function" is left on the stack. It occurs while draining said stack in the "for itemcount..." loop.BC_Programmer, thanks for the reply
Quote "At the comma it finds a ( immediately so never executes the loop body." so is this my mistake or did i followed the example from Wikipedia right?:
QuoteIf the token is a right parenthesis: Until the token at the top of the stack is a left parenthesis, pop operators off the stack onto the output queue. Pop the left parenthesis from the stack, but not onto the output queue. If the token at the top of the stack is a function token, pop it onto the output queue. If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. Quoteit also throws a subscript out of range error when POP() is called and the array only has one item. tried it with just one item and it works fine here: input = split("function")
|