2016-11-10 1 views
2

<<<이 모두 포함 된 언어를 구문 분석하고 있습니다. 내 알렉스 정의에서 나는에의보다 적게보다는으로해피 및 알렉 스의 토큰을 뒤로 밀기

tokens :- 

"<"    { token Lt } 
"<<"   { token (BinOp Shl) } 
내가 <<가 발생할 때마다 그래서, 왼쪽 교대로 토큰 화됩니다

하지 같은 것을 포함 무언가를 가지고있다. 이것은 토큰 화 후에 공백을 버리고 결국 1 < < 21 << 2을 구별하기 때문에 일반적으로 좋은 일입니다. 그러나, <<이 두 <으로 읽혀 지길 바란 다른 시간이 있습니다. 예를 들어, 내가 분명히

< <A> :: B > 

내가 여분의 경우에 수용하기 위해 내 해피 파서 규칙을 조정하기 위해 시도 할 수처럼 읽을 원하는

<<A>::B> 

같은 것들을 가지고 있지만, 그것은 심하게 확장 할 수 있습니다. 다른 명령형 파서 생성기에서는 토큰의 "부분"을 밀어 넣는 것과 같은 작업을 시도 할 수도 있습니다 (push_back("<")과 만났을 때 <<을 만났을 때만 < 만 필요했습니다).

다른 누구도 그런 문제가 있었습니까? 그렇다면 어떻게 처리 했습니까? 해피에 토큰을 "밀어 넣는"방법이 있습니까? 대신 공백 토큰을 유지하려고해야합니까? (실제로 저는 마지막 대안으로 기울여야합니다. 두통이 심하지 만 <<을 처리 할 수는 있지만 두 개의 공백 사이에 아무런 공백이 없어야합니다.) <.

답변

0

처음에 @ Jon의 답변을 읽으면서 많은 우선 순위 관련 문제 (우선 순위가 expr < exprexpr << expr)가 발생하여 많은 두통을 겪었습니다. 나는 최근에 (성공적으로) le 싱 <<을 하나의 토큰으로 다시 쓴다.이 솔루션은 두 가지였다 : (이전에 난 단지 <에 대한 규칙이 있었다 곳) 내가 총알을 비트와 <<에 대한 추가 규칙을 추가

  1. . 질문의 예를 들어 (<<A>::B>) 내 규칙 (실제 규칙이 실제로는 조금 더 복잡했다,하지만이 대답을하지 않습니다)

    ty_qual_path 
        : '<' ty_sum '>' '::' ident 
        | '<<' ty_sum '>' '::' ident '>' '::' ident 
    

    ty_qual_path 
        : '<' ty_sum '>' '::' ident 
    

    같은 것을에서 갔다. 하는 threaded lexer (section 2.5.2)를 사용하면 재고 할 수 있습니다 규칙의 {%% ... } RHS을 악용 :

  2. 나는 > 시작 토큰으로 처리하는 영리한 방법 (이 마지막 >> 토큰이었다 vector<i32,vector<i32>> 같은 것들을 주위에 문제를 일으킬 것)을 발견 Lookahead 토큰을 추가하고 pushToken 기능을 파서 모나드 (this turned out to be quite simple - here is exactly what I did)에 추가하십시오.

    gt :: {() } 
        : {- empty -} {%% \tok -> 
         case tok of 
         Tok ">>" -> pushToken (Tok ">") *> pushToken (Tok ">") 
         Tok ">=" -> pushToken (Tok "=") *> pushToken (Tok ">") 
         Tok ">>=" -> pushToken (Tok ">=") *> pushToken (Tok ">") 
         _   -> pushToken tok 
        } 
    

    같은 것을 그리고 다른 규칙 때마다 나는 > 기대뿐만 아니라 어떤 다른 토큰 >로 시작, 내가 gt> 토큰을 앞에 것이있을 수 있습니다 - 그럼 더미 규칙을 추가했다. 이것은 >이 아닌 >으로 시작할 수있는 다음 토큰을 조사하고 그 토큰을 하나의 > 토큰과 초기 토큰의 "나머지"토큰으로 변환하려고 시도 할 수 있습니다.

2

해피에서 이것을 표현하는 방법을 모르겠지만 별도의 "공백"토큰이 필요하지 않습니다. 공백없이 공백없이 입력 할 때 연산자 기호가 바로 뒤에 올 때 < 또는 >을 구별 할 수 있습니다.

그런 다음 연산자를 구문 분석하려면 일련의 각도와 연산자를 단일 토큰에 결합합니다. 대괄호로 처리하려면 평소와 같이 별도로 처리하십시오.

그래서 a << b

같이 tokenised 될 것이다 : 연산자를 구문 분석 할 때

identifier "a" 
left angle  -- joined with following operator 
operator "<" 
identifier "b" 

, 단일 operator "<<" 토큰을 생성, 다음 연산자 토큰 각 토큰을 연결. 각도 괄호 조건을 구문 분석 할 때

left angle 
operator "<" -- accepted as bracket 
identifier "A" 
right angle 
operator "::" 
identifier "B" 
operator ">" -- accepted as bracket 

, 당신은 모두 각 토큰 및 </> 사업자를 허용 :

<<A>::B>

는 다음과 같이 tokenised 될 것이다.

이것은 모호하지 않은 문법에 의존합니다. 연산자 이름이나 괄호로 묶은 것을 구문 분석해야하는지 여부.

+0

똑똑한 아이디어! Alex가 두 개의 토큰을 얻는 방법을 아직 찾지 못했지만 이것이 어떻게 작동하는지 볼 수 있습니다. 감사! – Alec

+0

@Alec : 그래, 필자는 Parsec에서이 기술을 사용해 본 적이있다. 예를 들어 try (오퍼레이터 <$> char '<' '* notFollowedBy 심볼) <|> LeftAngle <$> char'< '') Alex에서 직접 표현하는 것이 가능합니다. 어떻게 든 미리보기없이 인코딩 할 수 있습니다. –