2

我想在运算符旁边的调车场算法中实现“功能”,并从结果算法中制作一个小解释器,但默认算法会忽略语法错误的令牌使用。

有没有人写过解释器(或不写)想帮助我?这将帮助很多被这个问题困扰的人!

这里列出了一些测试,分流场函数忽略了函数调用中令牌的错误使用和/或缺少运算符/操作数:

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

我读到的一些研究:

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

对我的代码(vbscript)的解释以通过一些改进来测试它:

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

如果有人想分享那里的改进或有任何好的想法,请告诉我!

我的代码:

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!"

[编辑] 我希望我的解释器的语法与 BASIC 编程语言几乎完全相同。

类似 BASIC 的表达式示例:a + b * (c / func(x, y, func(z))) - d

语法错误表达式的示例:1 + 2 + + 3 3 func(,1,(,2)) ()

我的目标: 调车场算法的输出应该是正确的顺序,如果遇到语法问题应该有一个错误:空括号“()”或多个运算符/函数/整数彼此或错误的括号不允许在函数调用...

到目前为止,如果您以正确的方式键入表达式,则函数、整数和运算符的顺序是正确的!

如果它在 vbscript 本身中工作,它应该在这个算法中工作,如果不是,那么它不应该在这个脚本中工作,你得到一个错误......这就是我在这里想要做的......

我希望语法如何:(在“[]”之间表示可选,“;”是注释,在“##”之间是带有该标题的描述的链接......)

#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...]]]
4

0 回答 0