2

I want to implement "functions" in the shunting-yard algorithm beside operators and make a little interpreter from the resulting algorithm but syntactic incorrect usage of tokens is ignored by the default algorithm.

is there anyone that has written a interpreter (or not) wanting to help me? that would help a lot of people that are stuck with this problem!

here are some tests listed, the shunting-yard function ignores the wrong usage of tokens in function calls and/or missing operators/operands:

func(,1)
func(2,)
func(,,,,,)
()
(((()))()())
func((),(,))
func(1,2(3,4))
etc...

some research that i read:

http://www.reedbeta.com/blog/2011/12/11/the-shunting-yard-algorithm/
http://en.wikipedia.org/wiki/Shunting-yard_algorithm
http://rosettacode.org/wiki/Parsing/Shunting-yard_algorithm

explanation of my code (vbscript) to test this with a few improvements:

it allows usage of functions(beta)
it gives an error with most of the incorrect syntax
functions can be nested

if there are people that want to share there improvements or have any good ideas then please let me know!

my code:

Function Is_Empty(Stack)
If UBound(Stack) > - 1 Then
Is_Empty = False
Else
Is_Empty = True
End If
End Function
Function Peek(Stack)
If UBound(Stack) > - 1 Then
Peek = Stack(UBound(Stack))
End If
End Function
Function Pop(ByRef Stack)
If UBound(Stack) > - 1 Then
Pop = Stack(UBound(Stack))
ReDim Preserve Stack(UBound(Stack) - 1)
End If
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
Set Prec = CreateObject("scripting.dictionary")
With Prec
.Add "+", 1
.Add "-", 1
.Add "*", 2
.Add "/", 2
End With
Function Is_Operator(Op)
Is_Operator = Prec.Exists(Op)
End Function

Set Re = New RegExp
Re.Pattern = "[a-z0-9]+|[+\-/*,()]"
Re.Global = True
Set X = Re.Execute("func (1,1(1,1))")'//here the test code

Stack = Array() : Queue = Array() : Level = 0

For Each Token In X
Select Case Token
Case "func"
Call Push(Token, Stack)
Case "("
If Peek(Stack) = "func" Then
Level = Level + 1
Call Push("#", Queue)
End If
Call Push(Token, Stack)
Case ")"
Do While Not(Peek(Stack) = "(")
If Is_Empty(Stack) Then MsgBox "error: (", 48 : WScript.Quit
Call Push(Pop(Stack), Queue)
Loop
Discard = Pop(Stack)
If Peek(Stack) = "func" Then
Level = Level - 1
If Peek(Queue) = "," Then MsgBox "error: ,", 48 : WScript.Quit
Call Push(Pop(Stack), Queue)
End If
Case ","
If Level = 0 Then MsgBox "error: ,", 48 : WScript.Quit
If Peek(Queue) = "#" Then MsgBox "error: ,", 48 : WScript.Quit
If Peek(Queue) = "," Then MsgBox "error: ,", 48 : WScript.Quit
Do While Not(Peek(Stack) = "(")
If Is_Empty(Stack) Then MsgBox "error: ( or ,", 48 : WScript.Quit
Call Push(Pop(Stack), Queue)
Loop
Call Push(Token, Queue)
Case "+", "-", "*", "/"
A = Token
Do While Is_Operator(Peek(Stack))
B = Peek(Stack)
If Prec(A) < Prec(B) Then
Call Push(Pop(Stack), Queue)
Else
Exit Do
End If
Loop
If Peek(Queue) = "," Then MsgBox "error: wrong operator", 48 : WScript.Quit
Call Push(A, Stack)
Case Else
Call Push(Token, Queue)
End Select
Next
For I = 0 To UBound(Stack)
If Peek(Stack) = "(" Then MsgBox "error: )", 48 : WScript.Quit
Call Push(Pop(Stack), Queue)
Next

MsgBox Join(Queue, "|"),, Level
stack = array()

For Counter = 0 To UBound(Queue)
select case queue(counter)
case "func"
do while not(peek(stack) = "#")
if peek(stack) = "," then
l = l + 1
discart = pop(stack)
elseif is_empty(stack) then
exit do
else
F = F + INT(pop(stack))
end if
loop
discart = pop(stack)
call push(F, stack)
case "+","-","*","/"
B = pop(stack)
if is_empty(stack) then MsgBox "error: not enough values", 48 : WScript.Quit
A = pop(stack)
if not(isnumeric(a) and isnumeric(b)) then MsgBox "error: not numeric", 48 : WScript.Quit
select case queue(Counter)
case "+"
C = int(a) + int(b)
case "-"
C = int(a) - int(b)
case "*"
C = int(a) * int(b)
case "/"
C = int(a) / int(b)
case else
MsgBox "error: " & queue(Counter), 48 : WScript.Quit
end select
call push(c, stack)
case else
Call Push(queue(Counter), Stack)
end select
next
If UBound(Stack) > 0 Then MsgBox "too many values", 48 : WScript.Quit
If is_empty(Stack) Then MsgBox "error: not enough values", 48 : WScript.Quit

msgbox stack(0),0,"result!"

[EDIT] I want the syntax of my interpreter to be almost exactly the same as the BASIC programming language.

example of a BASIC like expression: a + b * (c / func(x, y, func(z))) - d

example of a syntactic wrong expression: 1 + 2 + + 3 3 func(,1,(,2)) ()

my goal: the output of the shunting yard algorithm should be in the right order, and if problems in the syntax are encountered there should be an error: empty brackets "()" or multiple operators/functions/integers after each other or wrong brackets in function calls are not allowed...

so far functions, integers and operators are in the right order if you type the expression the right way!

if it works in vbscript itself, it should work in this algorithm, if not then it should not work in this script ether, and you get an error... that's what i'm trying to do here..

how i want the syntax to be: (between "[]" means optional, ";" is a comment, between "##" is a link to the description with that title...)

#function#:
func([#expression#[, #expression#[, #expression#...]]]) ; 

#number#:
(0-9)+ ; integers from 0 to ...

#operator#:
( ; open bracket, can be a function grouping or part of an expression
) ; closing bracket (see open bracket for details)
  ; bracket rules: must start with an open and stop with a closed bracket,
  ; can be nested but there must be something inside them!
, ; function argument seperator
+ ; plus
- ; minus
* ; multiply (higher prec than + and -)
/ ; divide (same prec as multiply)

#operand#:
#number# or #function#

#expression#:
#operand# [#operator# #operand#[ #operator# #operand#[ and so on...]]]
Tom
  • 221
  • 1
  • 4
  • 16
  • 1
    also '1 1 +' is accepted and i think there are a lot of other problems to that i didn't mention.. – Tom Feb 18 '15 at 21:39
  • What is the desired behaviour in each case. Defining exactly what you what the output to be is the first step in writing parsers. – Salix alba Feb 19 '15 at 11:04
  • @Salix alba, have a look at the edit.. are you looking for some sort of schematic explanation of how i want this program's syntax to be? also thanks for the reply – Tom Feb 19 '15 at 12:10
  • i have also tried to make the question more clear and readable, i'm not English so its not easy to ask this kind of complex questions... apologies! – Tom Feb 19 '15 at 15:59
  • This is a common issue with using the Shunting-Yard algorithm. '1 + 2' = '+ 1 2' = '1 2 +'. The algorithm accepts a broader syntax than valid infix notation. – denver Apr 14 '15 at 18:36
  • @denver, Yes it is, on the moment i'm using the gold parser to make my programming languages and check the syntax. – Tom Apr 15 '15 at 20:22
  • @Tom, Not sure where you are at with it, but check out my answer at http://stackoverflow.com/a/29652095/2212458 to see how the Shunting-Yard algorithm can be enhanced to validate the infix format by keeping track of a state. – denver Apr 16 '15 at 13:09
  • I see, thanks for that, the only problem with your algorithm is that sometimes you can expect another operand or an operator at the same time.. example "a = 1 + -1" regards – Tom Apr 17 '15 at 14:53
  • @denver, (ignore previous comment) I see, thanks for that, the only problem with your algorithm is that sometimes you can expect another operand or an operator at the same time.. example "a = 1 + - (-1)", this is possible syntax in vb. but with some modifications it can possibly work the way i want, regards – Tom Apr 17 '15 at 14:58
  • @Tom I'm not sure I follow. The algorithm accepts an expression like "1+-(-1)" as valid input. Both of the '-' get identified as unary operators. – denver Apr 17 '15 at 15:37
  • @denver, " If token is a unary operator." ... "Set the state to ExpectOperand.", so the state is ExpectOperand, but "-" is a operator right? – Tom Apr 18 '15 at 19:43
  • @Tom, Yes. The unary negative is an operator, but it appears at the time you are expecting an operand. The unary negative has a higher precedence, so after it is applied an operand will be available in its place. – denver Apr 20 '15 at 13:25

0 Answers0