1
我想使用FsLex和FsYacc来分析一个简单的脚本语言,并且我在区分minus运算符和负数时遇到了问题。在F#lex/yacc分析器中区分'负'运算符和负数
如果我评估术语“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”被评估为负数,因为空白将被消耗。
但我认为这一定是一个普遍问题,必须有一个通用的解决方案。那么我该如何最好地处理这个问题?