2008-11-02 1 views
6

수 문자열과 변수 문자열 구분 :스칼라 콤비 파서 - 나는 숫자와 일치하는 문에서 변수를 나타내는 문자열을 나타내는 문자열을 구분하는 가장 좋은 방법에 대해 궁금해, 나는 케이 HORSTMANN의 콤비 파서 연습을하고 있어요

def factor: Parser[ExprTree] = (wholeNumber | "(" ~ expr ~ ")" | ident) ^^ { 
    case a: wholeNumber => Number(a.toInt) 
    case a: String => Variable(a) 
} 

두 번째 줄에 'case a : wholeNumber'는 유효하지 않습니다. 나는 정규 표현식에 대해 생각했지만, "case"로 작동하도록하는 방법을 찾지 못했습니다.

답변

6

나는 이것을 조금씩 나누어 사례 분석을 |으로 푸시합니다.

def factor: Parser[ExprTree] = (wholeNumber ^^ { Number(_.toInt) } 
           | "(" ~> expr <~ ")" 
           | ident ^^ { Variable(_) }) 

당신이 밑줄 구문에 익숙하지 않은 경우, 나는 사과 : 이것은 일반적으로 콤비 정말 LL (*) 구문 분석의 장점 중 하나입니다. 기본적으로 이는 "n th 매개 변수를 둘러싸는 함수 값으로 대체"합니다. 따라서 { Variable(_) }{ x => Variable(x) }과 같습니다.

여기에서 구문 마술의 또 다른 비트는 ~ 대신 ~><~ 연산자입니다. 이 연산자는 해당 구문 분석에 괄호의 구문 인을 포함해야하지만 결과는 expr의 결과로 전적으로 결정되어야합니다. 따라서 "(" ~> expr <~ ")""(" ~ expr ~ ")"과 정확히 일치하지만, expr에서 내부 결과 값을 검색하는 데 별도의 사례 분석이 필요하지 않습니다.

+0

우수! "오류 : 확장 된 함수의 매개 변수 유형이 누락되었습니다."라는 이유로 {Number (_. tont)}을 {x : String => Number (x)}로 변경해야만했습니다. 문제의 해결 방법이 있다면 여전히 궁금합니다. –

+0

사실, 실제로는 부분 함수 만 정의합니다. 그것은 당신이 입력에서 패턴 매칭을 할 수있게 해주는데, 이것이 정말로 유용한 이유입니다. 나는 대신 부분 함수 (대문자)를 사용하여 쉽게 내 대답을 작성할 수 있었지만, 필요하지는 않았습니다. :-) (~>와 <~)를 제외하고 있었을 것입니다. –

+0

전체 용어를 매칭하는 것을 의미하는 경우, 대답은 "아니오, 할 방법이 없습니다"라고 생각합니다. 'wholeNumber' 메소드가 String과 다른 컴포넌트 타입을 가진 Parser를 리턴하지 않는다면, 정말로 ident 또는 심지어 ("~"expr <~ ")"와 구별 할 방법이 없습니다. –

관련 문제