title: Shunting yard algorithm with functions
body: <p>my first post here :)</p>
  
  <p>I saw that there are a lot of questions about the Shunting yard algorithm but I
  hope there still are forum members that interested to help me with yet another question about this algorithm.</p>
  
  <p>I did search trough the other posts to see if my answer is already answered and i did some research on other forums and the internet to:</p>
  
  <pre><code>http://stackoverflow.com/questions/16877546/modifying-the-shunting-yard-algorithm-c
  http://www.computerhope.com/forum/index.php?topic=146535.0
  http://en.wikipedia.org/wiki/Shunting-yard_algorithm
  http://www.autoitscript.com/forum/topic/164627-shunting-yard-with-functions/
  </code></pre>
  
  <p>My code is written in vb-script because i like its simplicity and i don't know java or c like languages..</p>
  
  <p>my question:</p>
  
  <p>at the moment the algorithm allows wrong usage of "(" and ")"
  example: <strong>function((10,20,)30)</strong> is allowed but it is clearly not the right way to call a function..</p>
  
  <p>also i'm not sure if my code is written correctly, the pseudo-code from Wikipedia was my reference but its not very clear :(</p>
  
  <p>i'm also planning to extend it with if-else statements and nested loops and stuff because the main goal is to write some sort of interpreter in a vb like language as a learning project :)</p>
  
  <p>my code [edit]:</p>
  
  <pre><code>SET PRECEDENCE = CREATEOBJECT("SCRIPTING.DICTIONARY")
  WITH PRECEDENCE
      .ADD "^",3
      .ADD "*",2
      .ADD "/",2
      .ADD "%",2
      .ADD "+",1
      .ADD "-",1
      .ADD "FUNCTION",0
      .ADD "(",0
      .ADD ",",0
      .ADD ")",0
  END WITH
  
  '#############################################################################
  tokenArray = split("FUNCTION ( ( A , B ) , C )")
  msgbox SHUNTINGYARD(tokenArray)
  '#############################################################################
  
  FUNCTION SHUNTINGYARD(INPUT)
  
      TOKEN_QUEUE = ARRAY()
      TOKEN_STACK = ARRAY()
  
      FOR TOKEN_NUMBER = 0 TO UBOUND(INPUT)
          SELECT CASE INPUT(TOKEN_NUMBER)
  
              CASE "("
                  CALL PUSH(INPUT(TOKEN_NUMBER), TOKEN_STACK)
  
              CASE ")"
                  DO WHILE NOT( PRECEDENCE( PEEK(TOKEN_STACK) ) = 0 )
                      CALL PUSH(POP(TOKEN_STACK), TOKEN_QUEUE)
                      IF STACKISEMPTY(TOKEN_STACK) THEN CALL ERRORS("Can't find a matching ""("".", TRUE)
                  LOOP
  
                  IF PEEK(TOKEN_STACK) = "FUNCTION" THEN
                      DISCARD = POP(TOKEN_STACK)
                      CALL PUSH("@", TOKEN_QUEUE)
                  ELSE
                      DISCARD = POP(TOKEN_STACK)
                  END IF
  
              CASE ","
                  DO WHILE NOT( PRECEDENCE( PEEK(TOKEN_STACK) ) = 0 )
                      CALL PUSH(POP(TOKEN_STACK), TOKEN_QUEUE)
                      IF STACKISEMPTY(TOKEN_STACK) THEN CALL ERRORS("Can't find a matching function ""("".", TRUE)
                  LOOP
  
              CASE "+","-","*","/","^","%"
                  TOKEN_A = INPUT(TOKEN_NUMBER)
                  DO WHILE ISOPERATOR(PEEK(TOKEN_STACK))
                      TOKEN_B = PEEK(TOKEN_STACK)
                      IF (ASSOCIATIVITY(TOKEN_B) = "left" AND PRECEDENCE(TOKEN_A) = PRECEDENCE(TOKEN_B)) OR (PRECEDENCE(TOKEN_A) &lt; PRECEDENCE(TOKEN_B)) THEN
                          CALL PUSH(POP(TOKEN_STACK), TOKEN_QUEUE)
                      ELSE
                          EXIT DO
                      END IF
                  LOOP
                  CALL PUSH(TOKEN_A, TOKEN_STACK)
  
              CASE ELSE
                  CALL PUSH(INPUT(TOKEN_NUMBER), TOKEN_QUEUE)
  
          END SELECT
      NEXT
  
      FOR ITEMCOUNT = 0 TO UBOUND(TOKEN_STACK)
          IF PEEK(TOKEN_STACK) = "(" THEN CALL ERRORS("Can't find a matching "")"".", TRUE)'(
          CALL PUSH(POP(TOKEN_STACK), TOKEN_QUEUE)
      NEXT
  
      SHUNTINGYARD = JOIN(TOKEN_QUEUE,"|")
  
  END FUNCTION
  
  '#############################################################################
  
  FUNCTION ASSOCIATIVITY(ASSOC)
      SELECT CASE LCASE(ASSOC)
          CASE "^","\"
              ASSOCIATIVITY = "right"
          CASE ELSE
              ASSOCIATIVITY = "left"
      END SELECT
  END FUNCTION
  
  FUNCTION ISOPERATOR(ITEM)
      ISOPERATOR = LEN(ITEM) = 1 AND INSTR("+-*/%^",ITEM)
  END FUNCTION
  
  SUB PUSH(ITEM,BYREF STACK)
      IF UBOUND(STACK) &gt; -1 THEN
          REDIM PRESERVE STACK(UBOUND(STACK) + 1)
          STACK(UBOUND(STACK)) = ITEM
      ELSE
          STACK = ARRAY(ITEM)
      END IF
  END SUB
  
  FUNCTION POP(BYREF STACK)
      IF UBOUND(STACK) &gt; -1 THEN
          POP = STACK(UBOUND(STACK))
          REDIM PRESERVE STACK(UBOUND(STACK) - 1)
      END IF
  END FUNCTION
  
  FUNCTION STACKISEMPTY(STACK)
      IF UBOUND(STACK) &gt; -1 THEN
          STACKISEMPTY = FALSE
      ELSE
          STACKISEMPTY = TRUE
      END IF
  END FUNCTION
  
  FUNCTION PEEK(STACK)
      IF UBOUND(STACK) &gt; -1 THEN
          PEEK = STACK(UBOUND(STACK))
      END IF
  END FUNCTION
  </code></pre>