【问题标题】:Differentiate between 'minus' operator and negative numbers in F# lex/yacc parser区分 F# lex/yacc 解析器中的“减号”运算符和负数
【发布时间】:2014-11-03 22:10:42
【问题描述】:

我正在尝试使用 FsLex 和 FsYacc 解析简单的脚本语言,但在区分减号运算符和负数时遇到了问题。

如果我评估术语“1 - 2”,解析器将返回所需的 AST:Minus(NumberLiteral(1.0),NumberLiteral(2.0))。但是,如果我评估术语“1-2”,词法分析器将生成数字 1,然后是数字 -2,这不是有效的输入。

我制作了一个最小的程序来重现我的问题。 Ast 定义如下:

module Ast

type Expression =
  | NumberLiteral of double
  | Minus of Expression * Expression

词法分析器代码如下所示:

{
module Lexer
open Microsoft.FSharp.Text.Lexing
open Parser
}

let whitespace = ' '
let digit = ['0' - '9']
let number = '-'?digit+

rule token = parse
    | whitespace*   { token lexbuf }
    | '-'           { MINUS }
    | number        { lexbuf |> LexBuffer<_>.LexemeString |> System.Double.Parse |> NUMBER }
    | eof           { EOF }

解析器如下所示:

%{
open Ast
%}
%start start
%token EOF MINUS
%token <double> NUMBER
%type < Expression > start
%%

start: 
    | expression EOF    { $1 }

expression:
    | NUMBER            { NumberLiteral $1 }
    | expression
      MINUS expression  { Minus($1, $3) }

我最初的想法是不要将- 作为词法分析器中数字的一部分处理,并让解析器确定MINUS 标记是否应该产生减号运算符或负数。不幸的是,这也会导致输入“- 2”被评估为负数,因为会消耗空格。

但我假设这一定是一个普遍的问题,并且必须存在一个共同的解决方案。那么我该如何最好地处理呢?

【问题讨论】:

    标签: parsing f# fsyacc fslex


    【解决方案1】:

    通常的解决方案是-2 实际上是一个表达式。如果您认为评估 -2 效率太低(或者您可以将其作为生产 MINUS expression 中的特殊情况处理),您可以“常量折叠”——直接评估其参数为常量的表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-24
      • 1970-01-01
      • 1970-01-01
      • 2016-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-24
      相关资源
      最近更新 更多