-->

处理额外的运营商分流码(Handling extra operators in Shunting-y

2019-09-02 00:06发布

鉴于这样的输入: 3+4+算法使它转动到3 4 + +

我能找到的错误时,它的时间来执行后缀表达式。 但是,有没有可能在转换过程中被发现呢?

(维基百科的文章和互联网的文章我读过不处理这种情况下)

谢谢

Answer 1:

有效的表达式可以使用正则表达式从括号不匹配进行验证,放在一边。 (不匹配的括号将通过调度场算法被捕获在维基百科页面指示,所以我忽略那些。)

正则表达式如下:

PRE* OP POST* (INF PRE* OP POST*)*

哪里:

PRE  is a prefix operator or (
POST is a postfix operator or )
INF  is an infix operator
OP   is an operand (a literal or a variable name)

你链接的维基百科页面包括函数调用而不是数组下标; 如果要处理这些情况,则:

PRE  is a prefix operator or (
POST is a postfix operator or ) or ]
INF  is an infix operator or ( or ,
OP   is an operand, including function names

有一件事上面要注意的是PREINF是不相交的上下文; 也就是说,如果PRE是有效的,那么INF不,反之亦然。 这意味着,使用相同的符号都前缀运营商和中缀运算符是毫不含糊的。 此外, PREPOST是不相交的背景下,这样你就可以使用前缀和后缀运算符相同的符号。 但是,您不能使用后缀和中缀运营商相同的符号。 作为示例,考虑C / C ++操作符:

-  prefix or infix
+  prefix or infix
-- prefix or postfix
++ prefix or postfix

我隐式地使用该功能以上,以允许(被使用,也可以作为表达石斑鱼(有效前缀)和作为一个函数调用(中缀,因为它是函数名和参数列表之间;操作员是“呼叫”)。

这是最常见的实现是正则表达式作为一个状态机,因为只有两种状态:

 +-----+            +-----+
 |State|-----OP---->|State|
 |  1  |<----INF----|  2  |
 |     |---+        |     |---+
 +-----+   |        +-----+   |
    ^     PRE          ^     POST
    |      |           |      |
    +------+           +------+

我们可以称之为状态1“要操作数”和国家2“具有操作数”。 一个简单的执行仅分裂调度场算法在维基百科的介绍分为两个回路,这样的事情(如果你不喜欢goto ,它可以被淘汰,但它确实是呈现一个状态机最清晰的方式)。

want_operand:
  read a token. If there are no more tokens, announce an error.
  if the token is an prefix operator or an '(':
    mark it as prefix and push it onto the operator stack
    goto want_operand
  if the token is an operand (identifier or variable):
    add it to the output queue
    goto have_operand
  if the token is anything else, announce an error and stop. (**)

have_operand:
  read a token
  if there are no more tokens:
    pop all operators off the stack, adding each one to the output queue.
    if a `(` is found on the stack, announce an error and stop.
  if the token is a postfix operator:
    mark it as postfix and add it to the output queue
    goto have_operand.
  if the token is a ')':
    while the top of the stack is not '(':
      pop an operator off the stack and add it to the output queue
    if the stack becomes empty, announce an error and stop.
    if the '(' is marked infix, add a "call" operator to the output queue (*)
    pop the '(' off the top of the stack
    goto have_operand
  if the token is a ',':
    while the top of the stack is not '(':
      pop an operator off the stack and add it to the output queue
    if the stack becomes empty, announce an error
    goto want_operand
  if the token is an infix operator:
    (see the wikipeda entry for precedence handling)
    (normally, all prefix operators are considered to have higher precedence
    than infix operators.)
    got to want_operand
  otherwise, token is an operand. Announce an error

(*) The procedure as described above does not deal gracefully with parameter lists;
    when the postfix expression is being evaluated and a "call" operator is found, it's
    not clear how many arguments need to be evaluated. It might be that function names
    are clearly identifiable, so that the evaluator can just attach arguments to the
    "call" until a function name is found. But a cleaner solution is for the "," handler
    to increment the argument count of the "call" operator (that is, the open
    parenthesis marked as "infix"). The ")" handler also needs to increment the
    argument count.

(**) The state machine as presented does not correctly handle function calls with 0
    arguments. This call will show up as a ")" read in the want_operand state and with
    a "call" operator on top of the stack. If the "call" operator is marked with an
    argument count, as above, then the argument count must be 0 when the ")" is read,
    and in this case, unlike the have_operand case, the argument count must not be
    incremented.


文章来源: Handling extra operators in Shunting-yard