렉서 vs 파서


308

어휘 분석기와 파서는 이론상 그렇게 다른가?

코딩 공포 , 또 다른 블로그 게시물 인 정규 표현식을 싫어하는 것이 유행처럼 보입니다 .

그러나 인기있는 어휘 기반 도구 인 pygments , geshi 또는 prettify 는 모두 정규식을 사용합니다. 그들은 아무것도 렉스 것 같습니다 ...

언제 충분한가요? EBNF는 언제 필요합니까?

이 렉서에서 생성 된 토큰을 들소 또는 앤 트러 파서 생성기와 함께 사용한 사람이 있습니까?


2
예. autohotkey를 구문 분석하려고합니다. 피그먼트를 사용하여 구문 형광펜을 정말 빠르게 만들 수있었습니다. 그러나 antlr은 훨씬 오래 걸리고 있습니다. 두 도구 사이에서 많은 교차 수분을 보지 못했습니다.
Naveen

67
정규 표현식을 잘못 사용하는 것을 싫어하는 것은 유행입니다. 많은 사람들이 문맥없는 구문 분석이 필요할 때 정규식을 사용하려고합니다. 그들은 항상 실패합니다. 그리고 그들은 정규 표현 기술을 비난합니다. 그것은 망치가 엉망진창이라고 불평하는 것과 매우 흡사합니다. 사실이지만 많은 동정심을 느끼지 못할 것입니다.
Ira Baxter

2
고맙게도 antlr로 속도를 높이기 시작했습니다. 많은 렉싱은 컨텍스트가 없으며 때로는 컨텍스트에 따라 다릅니다.
Naveen

1
렉서 대 파서 문제의 한 가지 기본 측면은 렉서가 FSA (Finite Automata) 또는보다 정확하게 FST (Finite Transducer)를 기반으로한다는 것입니다. FSA 또는 FST 적용과 교차하여 대부분의 구문 분석 형식 (컨텍스트가 아닌)이 닫힙니다. 따라서 렉서에 대해 더 간단한 정규식 기반의 형식주의를 사용한다고해서 더 복잡한 파서 형식주의의 구문 구조의 복잡성이 증가하지는 않습니다. 이것은 언어의 구조와 의미를 정의 할 때 절대적으로 주요한 모듈성 문제 이며, 높은 투표 응답으로 행복하게 무시됩니다.
babou

그것은 렉서와 파서하지 않도록주의해야 다르게 예 LLLPG 및 ANTLR 이전 버전 렉서와 파서 모두 동일한 LL (K) 분석 시스템을 사용한다. 가장 큰 차이점은 정규 표현식은 일반적으로 어휘 분석기에 충분하지만 구문 분석기에는 충분하지 않다는 것입니다.
Qwertie

답변:


475

파서와 어휘 분석기의 공통점 :

  1. 입력에서 알파벳의 기호 를 읽습니다 .

    • 힌트 : 알파벳은 반드시 글자 일 필요는 없습니다. 그러나 파서 / 렉서가 이해하는 언어의 원자 기호이어야 합니다.
    • 어휘 분석기의 기호 : ASCII 문자.
    • 구문 분석기의 기호 : 문법의 터미널 기호 인 특정 토큰.
  2. 그들은이 기호 들을 분석하고 그들이 이해 한 언어 의 문법 과 일치 시키려고 노력합니다 .

    • 여기에 실제 차이점이 있습니다. 자세한 내용은 아래를 참조하십시오.
    • 렉서가 이해하는 문법 : 일반 문법 (Chomsky 레벨 3).
    • 구문 분석기가 이해하는 문법 : 문맥없는 문법 (Chomsky의 레벨 2).
  3. 그들은 찾은 언어 조각 에 의미 (의미)를 첨부 합니다.

    • 렉서는 분류하여 의미 첨부 할 어휘를 특정로 (입력으로부터 기호의 문자열) 토큰 . 예 :이 모든 어휘는 : *, ==, <=, ^는 C / C ++ 렉서가 토큰 "연산자"로 분류됩니다.
    • 파서는 입력 (문장)의 토큰 문자열을 특정 비 터미널 로 분류 하고 구문 분석 트리를 작성하여 의미를 부여 합니다. 예 : 모든 토큰 문자열 : [number][operator][number], [id][operator][id], [id][operator][number][operator][number]는 C / C ++ 파서에 의해 비단 '표현'으로 분류됩니다.
  4. 인식 된 요소에 추가 의미 (데이터)를 첨부 할 수 있습니다.

    • 어휘 분석기는 적절한 숫자를 구성하는 문자 시퀀스를 인식하면 이진수로 변환하여 "숫자"토큰으로 저장할 수 있습니다.
    • 마찬가지로 구문 분석기는 표현식을 인식하면 해당 값을 계산하고 구문 트리의 "expression"노드와 함께 저장할 수 있습니다.
  5. 그들은 모두 자신이 알고있는 언어 의 적절한 문장 을 출력에 만들어냅니다 .

    • Lexers는 토큰을 생성하는데 , 이는 토큰 이 인식 하는 정규 언어의 문장 입니다 . 각 토큰은 내부 구문 (레벨 2는 아니지만 레벨 3)을 가질 수 있지만 출력 데이터와이를 읽는 토큰에는 중요하지 않습니다.
    • 파서는 구문 트리를 생성하는데, 구문 트리는 인식 하는 문맥이없는 언어문장 을 나타냅니다 . 전체 문서 / 소스 파일이 적절한 문장 이므로 일반적으로 전체 문서 / 소스 파일에 대해 하나의 큰 트리입니다 . 그러나 파서가 출력에서 ​​일련의 구문 트리를 생성 할 수없는 이유는 없습니다. 예를 들어 일반 텍스트에 붙어있는 SGML 태그를 인식하는 파서 일 수 있습니다. 따라서 SGML 문서를 일련의 토큰으로 토큰 합니다 .[TXT][TAG][TAG][TXT][TAG][TXT]...

보다시피 파서와 토크 나이 저는 공통점이 많다. 한 파서는 다른 파서의 토크 나이저 일 수 있으며, 한 언어의 문장이 다른 상위 레벨의 알파벳 기호와 같은 방식으로 입력 토큰을 자체 알파벳의 기호 (토큰은 일부 알파벳의 기호 임)로 읽는다. 언어. 예를 들어, *-알파벳의 상징 M( "모스 부호 기호"로), 당신은 모스 부호로 인코딩 된 문자 이러한 점과 라인의 문자열을 인식하는 파서를 구축 할 수 있습니다. 언어 "모스 코드"의 문장이 될 수 토큰 다른 파서, 이러한 토큰언어의 원자 기호 (예 : "영어 단어"언어). 이 "영어 단어"는 "영어 문장"언어를 이해하는 일부 상위 레벨 구문 분석기의 토큰 (알파벳 기호) 일 수 있습니다. 그리고이 모든 언어는 문법의 복잡성 만 다릅니다 . 더 이상 없습니다.

그렇다면이 "Chomsky의 문법 수준"은 어떻습니까? Noam Chomsky는 문법을 복잡도에 따라 4 가지 수준으로 분류했습니다.

  • 레벨 3 : 정규 문법

    그들은 즉, 그들은 단지 알파벳의 기호로 구성 할 수 있습니다, 정규 표현식을 사용 ( a, b), 자신의 회씩 연결은 ( ab, aba, bbb. ETD), 또는 대안 (예를 들면 a|b).
    NFA (Nondeterministic Finite Automaton) 또는보다 나은 DFA (Deterministic Finite Automaton)와 같은 FSA (Finite State Automata)로 구현할 수 있습니다.
    정규 문법은 중첩 구문 , 예를 들어 올바르게 중첩 / 일치 괄호 (()()(()())), 중첩 HTML / BBcode 태그, 중첩 블록 등을 처리 할 수 ​​없습니다.이를 처리 하기위한 상태 오토마타는 무한히 많은 중첩 레벨을 처리하기 위해 무한히 많은 상태를 가져야하기 때문입니다.
  • 레벨 2 : 문맥없는 문법

    구문 트리에 중첩, 재귀, 자기 유사 분기를 가질 수 있으므로 중첩 구조를 잘 처리 할 수 ​​있습니다.
    스택을 사용하여 상태 자동 상태로 구현할 수 있습니다. 이 스택은 구문의 중첩 수준을 나타내는 데 사용됩니다. 실제로는 일반적으로 컴퓨터의 프로 시저 호출 스택을 사용하여 중첩 수준을 추적하고 구문의 모든 비 터미널 심볼에 대해 재귀 적으로 호출되는 프로 시저 / 함수를 사용하는 하향식 재귀 하강 파서로 구현됩니다.
    그러나 상황에 맞는 구문 으로는 처리 할 수 ​​없습니다 . 예를 들어 표현식이 x+3있고 한 상황에서 이것은 x변수의 이름 이 될 수 있고 다른 상황에서는 함수의 이름이 될 수 있습니다.
  • 레벨 1 : 상황에 맞는 문법

  • 레벨 0 : 무제한 문법
    재귀 적으로 열거 가능한 문법이라고도합니다.


70
오 예? 그렇다면 "단어 나 토큰"은 무엇입니까? 그들은 알파벳의 문자로 구성된 정규 언어의 문장 일뿐 입니다. 그리고 파서의 "구조"또는 "나무"는 무엇입니까? 또한 문장 이지만 특정 토큰이 알파벳 기호 인 다른 고급 언어로되어 있습니다. 차이점은 당신이 말한 것이 아니라 사용되는 언어복잡성 입니다. 파싱 ​​이론에 대한 핸드북으로 -1과 대면하십시오.
SasQ

3
@SasQ Lexers와 Parsers가 문법과 일련의 토큰을 입력으로 사용한다고 말하는 것이 공정한가?
Parag

4
바로 그렇다. 그들은 모두 그들이 인식하는 알파벳에서 일련의 기호를 가져옵니다. 렉서의 경우이 알파벳은 일반 문자로만 구성됩니다. 파서의 경우 알파벳은 정의 된대로 터미널 기호로 구성됩니다. 렉서를 사용하지 않고 한 문자 식별자와 한 자리 숫자 등을 사용하면 문자도 될 수 있습니다 (개발의 첫 단계에서 매우 유용합니다). 그러나 토큰은 좋은 추상화이기 때문에 일반적으로 토큰 (어휘 클래스)입니다. 실제로 사용되는 텍스쳐 (문자열)를 변경할 수 있으며 파서는 변경 사항을 보지 못합니다.
SasQ

6
예를 들어 STMT_END구문 분석기의 구문 기호 에 터미널 기호 를 사용하여 명령어의 끝을 나타낼 수 있습니다. 이제 어휘 분석기에 의해 생성 된 동일한 이름의 토큰을 가질 수 있습니다. 그러나 실제 lexeme을 변경할 수 있습니다. 예 : 당신은 정의 할 수 있습니다 STMT_END;소스 코드처럼 - C / C ++을 가지고. 또는 end파스칼 스타일과 비슷하게 정의 할 수 있습니다 . 또는 '\n'파이썬 에서처럼 줄 끝으로 명령을 끝내는 것으로 정의 할 수 있습니다 . 그러나 명령 구문 (및 파서)은 변경되지 않습니다 :-) 렉서 만 변경하면됩니다.
SasQ

24
Wikipedia와 Google의 시간은 도움이되지 않지만 3 분 안에 Chomsky의 문법을 설명했습니다. 감사합니다.
enrey

107

예, 이론과 구현면에서 매우 다릅니다.

Lexers는 언어 요소를 구성하는 "단어"를 인식하는 데 사용됩니다. 이러한 단어의 구조는 일반적으로 단순하기 때문입니다. 정규식은이 간단한 구조를 처리하는 데 매우 능숙하며, 어휘 분석기를 구현하는 데 사용되는 고성능 정규식 매칭 엔진이 있습니다.

파서는 언어 구의 "구조"를 인식하는 데 사용됩니다. 이러한 구조는 일반적으로 "정규 표현식"이 인식 할 수있는 것 이상으로, 그러한 구조를 추출하려면 "문맥에 민감한"파서가 필요하다. 상황에 맞는 파서는 작성하기가 어렵 기 때문에 "컨텍스트가없는"문법을 사용하고 구문 분석기 ( "기호 테이블"등)에 해킹을 추가하여 상황에 맞는 부분을 처리해야합니다.

렉싱이나 파싱 기술은 곧 사라지지 않을 것입니다.

그들은 스캐너가없는 GLR 파서에 의해 현재 탐색되고있는 바와 같이, "파싱"기술을 사용하여 "단어"를 인식하기로 결정함으로써 통일 될 수 있다. 일반적으로 필요하지 않은 문제에 더 일반적인 기계를 적용 할 때 런타임 비용이 발생하며 일반적으로 오버 헤드로 비용을 지불합니다. 빈 사이클이 많은 경우 오버 헤드가 중요하지 않을 수 있습니다. 많은 텍스트를 처리하면 오버 헤드가 중요하며 고전적인 정규식 파서는 계속 사용됩니다.


40
좋은 설명입니다. 당신의 비유에 추가 : 어휘 분석기는 단어를 올바르게 얻는 것에 관한 것이지만, 파서는 문장을 올바르게 얻는 것에 관한 것입니다. "스팟 런 참조"및 "스팟 런 참조"는 어휘 분석기에 관한 한 유효합니다. 구문 구조가 잘못되었다는 것을 판별하기 위해 구문 분석기가 필요합니다 (영어 문법).
Alan

트리 워커가 파서에있는 것처럼 파서는 어휘 분석기에 있다고 생각합니다. 나는 이론이 다르다는 것을 확신하지 못한다 : antlr.org/wiki/display/~admin/ANTLR+v4+lexers 그러나 나는 그들 사이의 관례의 차이점을 이해하기 시작하고있다.
Naveen

4
이론은 매우 다릅니다. 대부분의 파서 기술은 컨텍스트가없는 언어를 어느 정도 처리하려고합니다 (일부는 LALR의 일부만 수행하고 일부는 GLR의 일부만 수행). 대부분의 렉서 기술은 정규 표현식만을 시도합니다.
Ira Baxter

3
이론은 많은 사람들이 제안하고 다른 용어와 알고리즘을 사용하기 때문에 다릅니다. 그러나 자세히 살펴보면 유사점을 발견 할 수 있습니다. 예를 들어, 왼쪽 재귀 문제는 NFA의 비결정론 문제와 매우 유사하며 왼쪽 재귀 제거는 비결정론을 제거하고 NFA를 DFA로 변환하는 것과 유사합니다. 토큰은 토크 나이저 (출력)에 대한 문장이지만 파서 (입력)에 대한 알파벳 기호입니다. 차이점 (Chomsky 레벨)을 부정하지는 않지만 유사성이 디자인에 많은 도움이됩니다.
SasQ

1
제 사무실 동료는 범주 이론에 속했습니다. 그는 시브의 범주 이론 개념이 모든 종류의 패턴 일치를 어떻게 다루었으며, 추상 범주 사양에서 LR 파싱을 도출 할 수 있었는지 보여 주었다. 사실, 충분히 추상화하면 그러한 공통점을 찾을 수 있습니다. 범주 이론의 요점은 종종 "모든 방향으로"추상화 할 수 있다는 것입니다. 차이점을 지우는 범주 이론 파서를 만들 수 있다고 확신합니다. 그러나 그것을 실제로 사용하려면 특정 문제 영역으로 인스턴스화해야하며 그 차이는 실제로 나타납니다.
Ira Baxter

32

언제 충분한가요? EBNF는 언제 필요합니까?

EBNF는 실제로 문법 의 에 큰 도움이되지 않습니다 . 표준 Chomsky 's Normal Form (CNF) 문법 규칙에 비해 편의성 / 바로 가기 표기법 / "구문 설탕" 입니다. 예를 들어, EBNF 대안 :

S --> A | B

CNF에서 각 대체 생산물을 개별적으로 나열함으로써 달성 할 수 있습니다.

S --> A      // `S` can be `A`,
S --> B      // or it can be `B`.

EBNF의 선택적 요소 :

S --> X?

CNF에서 nullable 생산, 즉 빈 문자열 로 대체 할 수있는 생산 을 사용하여 달성 할 수 있습니다 (여기서는 빈 생산으로 표시됩니다. 다른 사람들은 엡실론 또는 람다 또는 교차 원을 사용합니다).

S --> B       // `S` can be `B`,
B --> X       // and `B` can be just `X`,
B -->         // or it can be empty.

B위 의 마지막 형태와 같은 형태의 제품 은 "지우기"라고합니다. 다른 제품에서 의미하는 것을 지울 수 있기 때문입니다 (제품은 다른 것이 아니라 빈 문자열).

EBNF에서 0 회 이상 반복 :

S --> A*

재귀 적 생산, 즉 어딘가에 자신을 포함시키는 것을 사용하여 망할 수 있습니다 . 두 가지 방법으로 수행 할 수 있습니다. 첫 번째는 왼쪽 재귀입니다 (Top-Down 재귀 하강 파서는 구문 분석 할 수 없으므로 일반적으로 피해야합니다).

S --> S A    // `S` is just itself ended with `A` (which can be done many times),
S -->        // or it can begin with empty-string, which stops the recursion.

빈 문자열 (궁극적으로) 뒤에 0 개 이상의 As가 생성된다는 것을 알고 있으면 동일한 문자열 ( 동일한 언어는 아닙니다! )은 right-recursion을 사용하여 표현할 수 있습니다 .

S --> A S    // `S` can be `A` followed by itself (which can be done many times),
S -->        // or it can be just empty-string end, which stops the recursion.

그리고 +EBNF에서 한 번 이상 반복 할 때 :

S --> A+

하나 A를 제외 *하고 이전 과 같이 사용하여 수행 할 수 있습니다 .

S --> A A*

CNF에서 다음과 같이 표현할 수 있습니다 (여기서 올바른 재귀를 사용합니다. 다른 사람을 운동으로 생각하십시오).

S --> A S   // `S` can be one `A` followed by `S` (which stands for more `A`s),
S --> A     // or it could be just one single `A`.

이제 정규식 (즉, 정규 문법 )에 대한 문법 을 터미널 기호로만 구성된 단일 EBNF 프로덕션으로 표현할 수 있는 문법으로 인식 할 수 있습니다. 보다 일반적으로 다음과 유사한 제작을 볼 때 정규 문법을 인식 할 수 있습니다.

A -->        // Empty (nullable) production (AKA erasure).
B --> x      // Single terminal symbol.
C --> y D    // Simple state change from `C` to `D` when seeing input `y`.
E --> F z    // Simple state change from `E` to `F` when seeing input `z`.
G --> G u    // Left recursion.
H --> v H    // Right recursion.

즉, (그냥 반복 만 빈 문자열 터미널 심볼, 대체 및 상태 변화에 대한 단순 비 단자를 이용하고, 반복을 달성하기 위해 단지 재귀를 사용한다 선형 재귀 -하지 분기 트리 형 않는 한). 이것보다 더 발전된 것은 없으며, 당신은 그것이 일반적인 구문인지 확신하고 그것을 위해 렉서와 함께 갈 수 있습니다.

그러나 구문에서 사소하지 않은 방식으로 재귀를 사용하는 경우 다음과 같이 트리와 유사하고 자체 유사하며 중첩 된 구조를 생성합니다.

S --> a S b    // `S` can be itself "parenthesized" by `a` and `b` on both sides.
S -->          // or it could be (ultimately) empty, which ends recursion.

어떤 식 으로든 단일 EBNF 프로덕션으로 해석 할 수 없기 때문에 정규 표현식으로 수행 할 수 없음을 쉽게 알 수 있습니다. 당신은 S무기한 으로 대체하여 결국 양쪽에 또 다른 as를 추가 할 것 b입니다. Lexers (보다 구체적으로 : Lexers가 사용하는 유한 상태 오토마타)는 임의의 수 (무한 수, 기억합니까?)로 계산할 수 없으므로 a너무 많은 수와 균등하게 일치 하는 수를 알 수 없습니다 b. 이와 같은 문법을 컨텍스트없는 문법 이라고 하며 (최소한) 파서가 필요합니다.

문맥없는 문법은 구문 분석하는 것으로 잘 알려져 있으므로 프로그래밍 언어의 구문을 설명하는 데 널리 사용됩니다. 그러나 더 있습니다. 독립적으로 동시에 더 많은 것을 계산할 때 더 일반적인 문법이 필요할 때가 있습니다. 예를 들어, 둥근 괄호와 대괄호를 사용할 수있는 언어를 설명하고 싶지만 서로 올바르게 쌍을 이루어야합니다 (중괄호가있는 중괄호, 둥근이있는 둥근). 이런 종류의 문법을 문맥 인식 이라고 합니다 . 왼쪽 (화살표 앞)에 둘 이상의 기호가 있음을 인식 할 수 있습니다. 예를 들면 다음과 같습니다.

A R B --> A S B

왼쪽에있는 이러한 추가 기호를 규칙을 적용하기위한 "컨텍스트"로 생각할 수 있습니다. 몇 가지 전제 조건이있을 수 등 사후 조건은 예를 들어, 위의 규칙을 대체 할 RS있지만,이 사이에 때만 AB사람들을 떠나 AB변경되지 않은 자신을. 이러한 종류의 구문은 완전한 튜링 머신이 필요하기 때문에 파싱하기가 실제로 어렵습니다. 완전히 다른 이야기이므로 여기서 끝내겠습니다.


1
EBNF는 "표준 Chomsky 's Normal Form (CNF) 문법 규칙에 대한 편의성 / 바로 가기 표기법 /"구문 설탕 ""입니다. 그러나 CNF는 당면한 주제와 거의 관련이 없습니다. EBNF는 표준 BNF로 쉽게 변환 될 수 있습니다. 기간. 표준 BNF의 구문 설탕입니다.
babou

11

요청에 따라 질문에 답변하기 (다른 답변에 나타나는 내용을 부적절하게 반복하지 않고)

허용 된 답변에서 제안한 것처럼 Lexers와 파서는 크게 다르지 않습니다. 둘 다 간단한 언어 형식화를 기반으로한다 : 어휘 분석기를위한 정규 언어와 파서 (parsers)를위한 문맥없는 (CF) 언어. 둘 다 상당히 간단한 계산 모델, 유한 상태 오토 마톤 및 푸시 다운 스택 오토 마톤과 관련이 있습니다. 정규 언어는 컨텍스트가없는 언어의 특수한 경우이므로 다소 복잡한 CF 기술 로 어휘 분석기를 작성할 수 있습니다. 그러나 적어도 두 가지 이유로 좋은 아이디어는 아닙니다 .

프로그래밍의 기본 요점은 시스템 구성 요소가 가장 적합한 기술을 사용하여 생산, 이해 및 유지 관리가 용이해야한다는 것입니다. 기술은 과도하게 사용되어서는 안되며 (필요한 것보다 훨씬 더 복잡하고 비용이 많이 드는 기술을 사용) 기술의 힘을 제한해서는 안되므로 원하는 목표를 달성하기 위해 기술적 인 왜곡이 필요합니다.

그렇기 때문에 "정규 표현을 싫어하는 것이 유행처럼 보입니다". 그들은 많은 것을 할 수 있지만, 구현시 다양한 확장과 제한이 이론상의 단순성을 다소 감소 시킨다는 사실을 언급하지 않고, 그것을 달성하기 위해 읽을 수없는 코딩이 필요한 경우가 있습니다. Lexers는 일반적으로 그렇게하지 않으며 일반적으로 토큰을 구문 분석하는 간단하고 효율적이며 적절한 기술입니다. 토큰에 CF 파서를 사용하는 것은 가능하지만 과잉입니다.

어휘 분석기에 CF 형식을 사용하지 않는 또 다른 이유는 전체 CF 전력을 사용하고 싶어 할 수 있기 때문입니다. 그러나 그것은 프로그램의 독서에 관한 구조적 문제를 일으킬 수 있습니다.

기본적으로 의미가 추출되는 프로그램 텍스트 구조의 대부분은 트리 구조입니다. 구문 분석 규칙에서 구문 분석 문장 (프로그램)이 생성되는 방법을 나타냅니다. 시맨틱 스는 구문 분석 규칙을 구성하여 구문 분석 트리를 작성하는 방식에서 구성 기술 (수학적 지향의 동질성)에 의해 파생됩니다. 따라서 트리 구조가 필수적입니다. 일반 세트 기반 렉서로 토큰이 식별된다는 사실은 상황을 변경하지 않습니다. 일반적으로 구성된 CF는 여전히 CF를 제공하기 때문에 (일반적인 변환기에 대해 매우 느슨하게 말하고 문자 스트림을 토큰 스트림으로 변환합니다).

그러나 CF로 구성된 CF (CF 변환기를 통해 ... 수학에 대해 죄송합니다)는 반드시 CF를 제공 할 필요는 없으며보다 일반적이지만 일을 다루기 어렵게 만들 수 있습니다. 따라서 CF는 사용할 수 있지만 어휘 분석기에 적합한 도구는 아닙니다.

정규 언어와 CF의 주요 차이점 중 하나는 정규 언어 (및 변환기)가 다양한 방식으로 거의 모든 형식주의와 매우 잘 구성되는 반면 CF 언어 (및 변환기)는 그 자체로도 (몇 가지 예외를 제외하고) 그렇지는 않습니다.

(일부 변환기는 일부 구문 오류 처리 기술의 공식화와 같은 다른 용도로 사용될 수 있습니다.)

BNF는 CF 문법을 표현하기위한 특정 구문입니다.

EBNF는 BNF의 구문 설탕입니다 규칙적인 표기법을 사용하여 BNF 문법의 더 정확한 버전을 제공하는 . 항상 동등한 순수 BNF로 변환 될 수 있습니다.

그러나 정규 표기법은 종종 어휘 요소의 구조에 해당하는 구문의 이러한 부분을 강조하기 위해 EBNF에서 자주 사용되며 나머지는 곧바로 BNF로 표시됩니다. 그러나 절대적인 규칙은 아닙니다.

요약하면, 토큰의 간단한 구조는 일반 언어의 간단한 기술로 더 잘 분석되는 반면 (프로그램 구문의) 언어의 트리 지향 구조는 CF 문법으로 더 잘 처리됩니다.

나는 또한 AHR의 답변을 볼 것을 제안 합니다.

그러나 이것은 왜 나무가 문제인가?

트리는 구문을 지정하기위한 좋은 기초입니다.

  • 그들은 텍스트에 간단한 구조를 제공합니다

  • 위에 나타낸 바와 같이, 수학적으로 잘 이해 된 기술 (동질성을 통한 합성)을 사용하여, 그 구조에 기초하여 의미론을 텍스트와 연관시키는 것이 매우 편리하다. 수학 형식주의의 의미를 정의하는 기본 대수 도구입니다.

따라서 AST (Abstract Syntax Trees)의 성공으로 알 수 있듯이 좋은 중간 표현입니다. 많은 전문가가 사용하는 구문 분석 기술 (LL 또는 LR과 같은)이 CF 문법의 하위 집합에만 적용되므로 나중에 AST에서 수정되는 문법 왜곡이 발생하기 때문에 AST는 종종 구문 분석 트리와 다릅니다. CF 문법을 받아들이는보다 일반적인 파싱 기술 (동적 프로그래밍 기반)을 사용하면이를 피할 수 있습니다.

프로그래밍 언어가 CF가 아닌 문맥 인식 (CS)이라는 사실에 대한 진술은 임의적이며 논쟁의 여지가 있습니다.

문제는 구문과 의미의 분리가 임의적이라는 것입니다. 선언 또는 형식 동의 확인은 구문의 일부 또는 의미의 일부로 볼 수 있습니다. 자연어에서의 성별 및 숫자 합의도 마찬가지입니다. 그러나 복수의 동의어가 단어의 실제 의미 론적 의미에 의존하여 구문과 잘 맞지 않는 자연어가 있습니다.

dentational 의미론에서 프로그래밍 언어의 많은 정의는 의미론에서 선언 및 유형 검사를 배치합니다. Ira Baxter 가 말한대로 가 구문 분석에 필요한 컨텍스트 감도를 얻기 위해 CF 파서가 해킹당하는 것은 상황에 대한 임의의 관점에 달려 있습니다. 일부 컴파일러에서는 핵으로 구성 될 수 있지만 반드시 그럴 필요는 없습니다.

또한 CS 파서 (여기 다른 답변에 사용 된 의미)가 구축하기가 어렵고 효율성이 떨어지는 것은 아닙니다. 또한 필요할 수있는 상황에 맞는 감도를 눈에 띄게 표현하기에는 부적절하다. 그리고 자연스럽게 프로그램의 의미를 도출하는 데, 즉 컴파일 된 코드를 생성하는 데 편리한 구문 구조 (예 : 구문 분석 트리)를 생성하지 않습니다.


예, 파싱 트리와 AST는 다르지만 실제로 유용한 방법은 아닙니다. :이 내 설명을 참조하십시오 stackoverflow.com/a/1916687/120163
아이라 박스터

@IraBaxter 나는 당신에 동의하지 않지만, 나는 지금 당신의 게시물에 대한 명확한 답변을 작성할 시간이 없습니다. 기본적으로, 당신은 실용적인 관점을 취하고 있습니다 (또한 자신의 시스템을 방어한다고 생각합니다). 일부 시스템에서와 같이 결정적인 것이 아니라 일반적인 CF 파서 (GLR이 가장 효율적이지 않을 수도 있음)를 사용하기 때문에 훨씬 더 쉽습니다. 저는 AST를 참조 표현으로 간주합니다.이 표현은 공식적으로 정의 된 처리, 입증 가능한 변형, 수학적 증거, 여러 구체적인 표현에 대한
파싱

"실용적인"관점은 그들이 유용한 방식으로 크게 다르지 않다고 주장하는 이유입니다. 그리고 나는 (ad hoc AST)를 사용하면 "아마도 올바른 변환"을 제공한다고 믿지 않습니다. 귀하의 임시 AST는 처리되는 언어의 실제 문법과 명백한 관계가 없습니다 (여기서, 우리 시스템은 "AST"가 BNF와 동형 일 가능성이 있다는 점에서 방어 적입니다). 임시 AST는 "복수의 구체적인 표현을 분석 할 수있는 추가 기능을 제공하지 않습니다. GLR에 대한 이의 제기 (가장 효율적이지 않음)는 무의미 해 보이지 않습니다.
Ira Baxter

사실 저는 귀하의 의견에 대한 귀하의 반대 의견을 전혀 이해하지 못합니다. "정답"이라고 써야합니다.
Ira Baxter

@IraBaxter 의견은 적절한 답변을하기에는 너무 제한적입니다 (제안?). "Ad Hoc"은 AST I 옹호자를위한 적절한 규정자가 아니며, 때로는 참조 구문이어야합니다. 이것은 컴퓨터 과학에서 AST의 개념의 역사와 분류 된 대수학의 용어 (나무)로서의 공식 시스템의 역사와 해석을 모두 고려하여 역사적으로 사실입니다. AST는 참조 형식이 아니라 파생 형식입니다. 최신 증명 시스템 및 자동 프로그램 생성도 참조하십시오. 다른 사람이 디자인 한 구체적인 구문을 사용해야한다는 사실에 편견이있을 수 있습니다.
babou

7

컴파일러의 분석 부분이 일반적으로 어휘 분석 및 구문 분석 (구문 분석) 단계로 분리되는 데는 여러 가지 이유가 있습니다.

  1. 디자인의 단순성이 가장 중요한 고려 사항입니다. 어휘 분석과 구문 분석을 분리하면 종종 이러한 작업 중 하나 이상을 단순화 할 수 있습니다. 예를 들어 주석과 공백을 구문 단위로 처리해야하는 구문 분석기는 예입니다. 주석과 공백을 가정 할 수있는 것보다 상당히 복잡한 것은 어휘 분석기에 의해 이미 제거되었습니다. 우리가 새로운 언어를 디자인하는 경우 어휘와 구문 문제를 분리하면 전반적인 언어 디자인이 더 깨끗해질 수 있습니다.
  2. 컴파일러 효율성이 향상되었습니다. 별도의 어휘 분석기를 사용하면 구문 분석 작업이 아닌 어휘 작업 만 처리하는 특수 기술을 적용 할 수 있습니다. 또한 입력 문자를 읽는 특수 버퍼링 기술로 컴파일러 속도를 크게 높일 수 있습니다.
  3. 컴파일러 이식성이 향상되었습니다. 입력 장치 별 특성은 어휘 분석기로 제한 될 수 있습니다.

resource___ 컴파일러 알프레드 V. ABO 컬럼비아 대학 모니카 S. 램 스탠포드 대학 라비 세티 어바이어 제프리 D. Ullman은 스탠포드 대학 부산물 작성 (2 판)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.