2012-07-01 3 views
5

Ocamlyacc와 비슷한 Menhir 파서를 사용하여 연산자에 동적 특성 (우선 순위 및 우선 순위)이있는 언어를 구문 분석하려고합니다. 렉싱 단계에서 모든 연산자는 OP:string 토큰을 채 웁니다 (따라서 "+"는 (OP "+") 등으로 변합니다).Menhir/Ocamlyacc에서 연산자에 대한 동적 우선 순위 및 우선 순위 지정

연산자 속성은 구문 분석시 결정되며 연산자와 해당 특성을 연결하는 테이블을 채 웁니다. 이 테이블이 주어지면이 테이블의 데이터를 기반으로 연산자를 파싱하는 규칙의 우선 순위를 동적으로 변경하도록 Menhir에 지시 할 수 있습니까?

감사합니다. CharlieP.

답변

10

"잘못하고 있습니다"라고 대답하는 것에 유감스럽게 생각합니다. 관련성이 낮은 순서로 건설적인 희망을 갖는 세 가지 반대가 있습니다.

  1. Menhir은 동적 문법 업데이트를위한 것이 아닙니다. 구문 분석시 문법을 변경해야한다면 GLR 파서 Dypgen과 같은이 기능을 제공하는 도구를 사용해야합니다. Dypgen 매뉴얼은 사용자의 필요에 부합하지 않을 수도있는 제약적인 방식으로 운영자 우선 순위를 동적으로 업데이트 할 가능성을 언급합니다 (새로운 운영자 및 해당 우선 순위를 추가 할 수 있지만 기존 우선 순위는 변경하지 않는 것 같습니다). Dypgen manual (PDF) 페이지의 6.6을 참조하십시오 ... 42.

  2. 동적으로 CFG 문법을 업데이트하는 것은 사용자 정의 연산자 우선 순위를 처리하는 최선의 방법이 아닙니다. Agda는 매우 일반적인 사용자 정의 mixfix 연산자를 가지고 있으며 솔루션은 대략 다음과 같습니다. CFG 파서를 사용하여 정적으로 알려진 문법 구조를 파싱 할 수 있습니다. 그러나 멋진 우선 순위와 연관성을 사용할 수있는 표현을 위해 토큰. 예를 들어, let x = if foo then x + y * z else barLet(x, If(foo, Expr(x, +, y, *, z), bar)과 같은 것으로 구문 분석됩니다. 나중에 특수화 된 패스가 필요한 정보를 모아서 Expr 노드로 파싱 한 후 특수 구조로 파싱 할 수 있습니다. 파서 생성기를 사용하여 (정적으로 알려진 리치 CFG) 무엇이 좋은지 알아보고 복잡하고 잘못 정의 된 동적 요소에 대해 사후 처리 단계를 사용하십시오. Agda 사람들은이 주제와 관련하여 몇 가지 문헌을 가지고 있습니다. 예를 들어, Parsing Mixfix Operators, Danielsson and Norell, 2009.

    디자인 관점에서 필자는 렉싱과 파싱을 몇 가지 다른 패스에서 분리 할 것을 강력히 권합니다 자체 구조를 동적으로 변경하려고 시도하는 대신 이전 구조에서 수집 한 정보 만 사용합니다. 훨씬 간단하고 훨씬 강력한 것을 갖게 될 것입니다.

  3. 동적 또는 사용자 정의 우선 순위와 우선 순위는 제 의견으로는 약간 악합니다. OCaml은 운영자 우선 순위 우선 순위가 처음 몇 문자 (예 : @, @@@+과 같이 모두 오른쪽 연관)로 결정되는 다른 시스템을 사용합니다. 중온 연산자를 선택하는 사람들에게는 약간 제한적이지만, 코드 리더은 학습 할 문법 규칙이 하나뿐이므로 새로운 코드 조각에 눈을 동적으로 적용하지 않아도 훨씬 편안합니다. . 완전히 다른 구문을 사용하여 야생의 외부 코드를 삽입하려는 경우 인용 부호 체계 (예 : camlp4 <:foo<...>>)는 연산자 수준의 연관성 및 우선 순위를 사용하는 것보다 훨씬 강력하며 구문 분석하기가 훨씬 쉽습니다.

    다른 말로하면, 프로젝트는 서로 다른 요구를 가지고 있으며, 제가 잘 모르는 일부 응용 프로그램에 대해 연산자 우선 순위와 연관성을 동적으로 변경해야한다고 주장한다면 완전히 이해할 수 있습니다.주변을 둘러 보는 유일한 방법은 아니며 때로는 일관성과 단순성이 절대적인 유연성보다 낫다는 것을 명심하십시오.