2014-11-03 9 views
1

FsLex와 FsYacc를 사용하여 간단한 스크립트 언어를 구문 분석하려고하는데 마이너스 연산자를 음수와 구별하는 데 문제가 있습니다.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"입력이 음수로 평가 될 수도 있습니다.

그러나 일반적인 문제 여야하며 일반적인 해결 방법이 있어야한다고 가정합니다. 그럼 어떻게 처리해야합니까?

답변

1

보통 해결책은 실제로 -2이라는 표현입니다. -2을 평가하기에는 너무 비효율적이라고 생각하면 (또는 프로덕션에서 특별한 경우로 처리 할 수 ​​있습니다.) MINUS expression) "상수 배수"- 인수가 상수 인 표현식을 직접 평가할 수 있습니다.