OperatorPrecedenceParser
을 사용하여 대소 문자를 구별하지 않는 중절 연산자를 얻으려면 입력을 사전 처리하여 문자열 리터럴로 구분 된 텍스트로 구문 분석합니다. 텍스트 부분은 대문자로 표기 할 필요가있는 삽입 연산자를 검색합니다 (OPP
에 알려진 연산자와 일치하도록). 실제 구문 분석이 수행됩니다.전체 입력을 두 번 파싱하기
제 질문은 두 단계를 단일 구문 분석기로 결합 할 수 있습니까? 나는
// preprocess: Parser<string,_>
// scalarExpr: Parser<ScalarExpr,_>
let filter = (preprocess .>> eof) >>. (scalarExpr .>> eof)
을 시도했지만 겉보기
scalarExpr
를 기대하고, 입력의 끝에 실패합니다. 입력은
preprocess
과
scalarExpr
에 의해 개별적으로 파싱 될 수 있으므로
eof
의 문제 일 것이라고 추측합니다.하지만 올바르게 이해할 수없는 것 같습니다. 이것이 가능한가?
다음은 참조 할 수있는 다른 파서입니다.
let stringLiteral =
let subString = manySatisfy ((<>) '"')
let escapedQuote = stringReturn "\"\"" "\""
(between (pstring "\"") (pstring "\"") (stringsSepBy subString escapedQuote))
let canonicalizeKeywords =
let keywords =
[
"OR"
"AND"
"CONTAINS"
"STARTSWITH"
"ENDSWITH"
]
let caseInsensitiveKeywords = HashSet(keywords, StringComparer.InvariantCultureIgnoreCase)
fun text ->
let re = Regex(@"([\w][\w']*\w)")
re.Replace(text, MatchEvaluator(fun m ->
if caseInsensitiveKeywords.Contains(m.Value) then m.Value.ToUpperInvariant()
else m.Value))
let preprocess =
stringsSepBy
((manySatisfy ((<>) '"')) |>> canonicalizeKeywords)
(stringLiteral |>> (fun s -> "\"" + s + "\""))
운영자가 너무 오래되어 관심있는 모든 대소 문자 조합을 OPP에 추가 할 수 없습니다 (예 : 약간의 도우미 기능 사용). 전처리 중에 연산자를 어떻게 대문자로합니까? 입력 버퍼를 직접 변경합니까? 입력을 두 번 파싱하려면 시작 부분으로 되돌아 가거나 새 CharStream을 만들어야합니다. –
다섯 가지 연산자가 있습니다. (아마도 앞으로는 더 많을 것입니다.) 가장 긴 문자는 10 자입니다. 'preprocess'는 대문자로 새로운 문자열을 반환합니다. – Daniel
다른 파서로 내 질문을 업데이트했습니다. 방금''.''대신''=''이 필요하다는 것을 알았지 만 유형이 제대로 작동하지 않으므로 지금 당황 스럽습니다. – Daniel