사용자 정의 도메인 특정 언어를 구문 분석하고 싶습니다. 이 언어는 일반적으로 수학 표기법에 가깝습니다 (자연어를 구문 분석하지 않습니다). 사용자는 다음과 같이 BNF 표기법으로 DSL을 정의합니다.
expr ::= LiteralInteger
| ( expr )
| expr + expr
| expr * expr
like like 입력은 1 + ( 2 * 3 )
승인되어야하고, like like 입력 1 +
은 올바르지 않은 것으로 거부되어야하며, like like 입력 1 + 2 * 3
은 모호한 것으로 거부되어야합니다.
여기서 가장 어려운 점은 사용자에게 친숙한 방식으로 모호한 문법에 대처하는 것입니다. 문법을 모호하지 않게 제한하는 것은 선택 사항이 아닙니다. 이것이 언어의 방식입니다. 아이디어는 모호성을 피할 필요가 없을 때 괄호를 생략하는 것을 선호합니다. 표현이 모호하지 않은 한 구문 분석해야하며, 그렇지 않은 경우 거부해야합니다.
내 파서는 컨텍스트가없는 문법, 모호한 문법에서 작동해야하며 모호하지 않은 모든 입력을 수용해야합니다. 허용되는 모든 입력에 대해 구문 분석 트리가 필요합니다. 유효하지 않거나 모호한 입력의 경우 이상적으로는 좋은 오류 메시지를 원하지만 시작하려면 먼저 얻을 수있는 것을 취할 것입니다.
일반적으로 비교적 짧은 입력에서 파서를 호출하고 때로는 더 긴 입력을 사용합니다. 따라서 점진적으로 빠른 알고리즘이 최선의 선택이 아닐 수 있습니다. 20 자 미만의 기호, 20 자에서 50 자 사이의 19 %, 1 %의 드문 입력 사이에 약 80 %의 입력 분포를 최적화하고 싶습니다. 유효하지 않은 입력 속도는 큰 문제가되지 않습니다. 또한, 나는 1000에서 100000 개의 입력마다 DSL의 수정을 기대합니다. 몇 분이 아니라 몇 초 동안 내 문법을 전처리 할 수 있습니다.
일반적인 입력 크기를 고려할 때 어떤 파싱 알고리즘을 조사해야합니까? 오류보고가 내 선택에 영향을 주어야합니까, 모호하지 않은 입력을 구문 분석하는 데 집중해야하고 오류 피드백을 제공하기 위해 완전히 분리 된 느린 파서를 실행해야합니까?
(필요한 프로젝트 (이전의 프로젝트)에서 CYK를 사용했습니다 . 이는 구현하기가 어렵지 않고 입력 크기에 적절하게 작동했지만 매우 멋진 오류는 발생하지 않았습니다.)
x+y+z
?
+
으므로 x+y+z
실제로 모호합니다.