Rascal MPL에서 SDF의 {피하기를 사용하는 방법
-
21-12-2019 - |
문제
나는 rascal mpl 를 사용하여 섬 문법을 디자인하려고 노력하고 있습니다. 그러나 나는 문제 :
SDF에서 섬 문법을 구현할 때 매우 일반적인 접근 방식은 {피하기} 속성을 사용하여 "catch-all"물 생산을 정의하는 것입니다. 이렇게하면 파서 가이 프로덕션을 사용할 수있는 경우 파서 가이 프로덕션을 방지합니다. 이렇게하면 다른 프로덕션을 WhiTout 유도 성을 바꿀 수있는 기본 동작 을 지정할 수 있습니다. 매우 간단한 예는 다음과 같습니다 :
context free syntax
Chunk* -> Input
Water -> Chunk
lexical syntax
~[\t\n\ ]+ -> Water {avoid} // avoid the Water production
.
Rascal MPL을 사용 하여이 동작을 재현했습니다. 내 목표는 C / C ++ 코드 내부의 모든 조건부 전 처리기 지시문을 수집하고 수상 생산을 사용하여 나머지 입력을 건너 뛸 섬 문법을 만드는 것입니다.
layout LAYOUT = [\t\n\ ];
lexical WATER = ![\t\n\ ]+;
start syntax Program = Line*; // program consists of lines
syntax Line = ConditionalDirective // preprocessor directives
> WATER; // catch-all option
syntax ConditionalDirective = "#ifdef"
| "#ifndef"
| "#if"
| "#elif";
.
conditionaldirective 프로덕션을 ">"운영자를 사용하여 더 높은 우선 순위를 부여함으로써 {피하기} 효과를 생성하려고 시도했지만, 이것은 분명히 작동하지 않습니다. 파스 트리에는 여전히 모호함이 들어 있습니다.
#ifdef asd
.
위의 코드를 구문 분석하면 다음과 같이 보이는 구문 분석 트리를 얻습니다.
rascal에서 알 수있는 한
문서화 , "우선 순위"를 사용하면 내 경우에 들어가는 방법이 아닐 수도 있지만 다른 가능성은 보이지 않습니다. Rascal의 저자가 모든 SDF 문법이 악순한 문법으로 변환 될 수 있다고 명확하게 주도하기 때문에 나는 길이가 있다고 가정합니다.
라스키 MPL을 사용하여 SDFS {피하기} 기능을 재현하는 방법이 있습니까? 아니면 어떻게 든 파싱 포리스트를 필터링 할 수있어 우선 순위를 다시 적용 할 수 있습니까?
해결책
짧은 대답 : SDF2가 사후 분석 필터를 사용하지 마십시오. Rascal에서는이 스스로를 정의 할 수 있습니다. https://github.com/cwi-swat/rascal/blob/master/src/org/rascalmpl/library/lang/sdf2/filters/preferavoid.rsc in mimics SDF2는 주입 체인을 무시하고 계산하지 않고 행동을 피합니다. 문법에서 가져오고 SDF2와 마찬가지로 @avoid 및 @prefer 태그를 사용하거나 자신의 필터를 작성할 수 있습니다.
주의 사항 : SDF2에서 수자원 행동을 정의하기에 일반적으로 피해야하고 Rascal이 아닌 것은 아닙니다. 그 이유는 물이 그 대안보다 길어질 수 있다는 것입니다. 양념을 선호하고 피하는 것은 동등한 길이의 대안 만 선택할 수 있습니다. ASTALIFIRITIFIRIFER는 모든 대안으로 계산하고 물이 적은 파생을 선택하는 것입니다.
다른 문제가 있고 피해야 할 때 사용이 간섭을 시작할 것이고, 특히 그들이 계산되었을 때 간섭을 시작한다는 것입니다. 특정의 비 터미널 또는 심지어 대체 규칙에 대한 필터를 전문으로써 Rascal에서는 피할 수 있습니다.
다른 옵션은 \와! 불변 연산자. 설명서를 참조하십시오. 그러나, 그리고 모든 것 Post Parse 필터링 옵션은 현재 무슨 일이 일어나고 있는지 제어하기 때문에 섬 문법을 다루는 가장 좋은 방법이라고 믿습니다.