프로그래밍 언어, 정규 표현식 및 공식 언어의 관계는 무엇입니까


25

나는이 질문에 대한 답을 인터넷을 둘러 보았고 모두가 나를 제외하고 대답을 암시 적으로 알고있는 것처럼 보입니다. 아마도 이것은 관심있는 유일한 사람들이 주제에 대한 고등 교육을받은 사람들이기 때문일 것입니다. 반면에 나는 고등학교 과제를 위해 깊은 곳에서 던져졌습니다.

제 질문은 프로그래밍 언어가 공식 언어와 얼마나 정확하게 관련되어 있습니까? 내가 읽는 모든 곳에서 "공식 언어는 프로그래밍 언어의 문법을 정의하는 데 사용된다"는 내용이있다.

이제 내가 수집 한 것에서 공식 언어는 특정 기호 세트 (언어의 알파벳)에 적용되는 일련의 생산 규칙입니다. 이러한 생산 규칙은 다음과 같은 일련의 변환을 정의합니다.

b -> a

aaa->c

이것은 다음과 같이 적용될 수 있습니다.

abab->aaaa aaaa-> ca

부수적으로, 공식 언어의 알파벳을 {a, b, c}로 정의하면 a와 b는 터미널이 아니며 c는 변환 할 수 없으므로 터미널입니다 (잘못되면 수정하십시오) 그).

그렇다면이 모든 것이 프로그래밍 언어에 어떻게 적용 되는가? 문법이 올바른지 확인하기 위해 정규식을 사용하여 텍스트 형식의 언어를 구문 분석하는 데 종종 사용됩니다. 이것은 말이됩니다. 그런 다음 정규 표현식이 공식 언어로 정의된다고 명시되어 있습니다. 정규식을 나타내는 유한 상태 오토마타가 목표점에 도달하는지 여부에 따라 정규식은 (최소한의 경험으로는) 참 또는 거짓을 반환합니다. 내가 볼 수있는 한, 그것은 변형과 관련이 없습니다 *.

프로그램 자체를 컴파일하기 위해 공식 언어가 코드를 연속적으로 낮은 수준의 코드로 변환하여 하드웨어가 이해할 수있는 복잡한 규칙 세트를 통해 어셈블리에 도달 할 수 있다고 생각합니다.

이것이 저의 혼란스러운 관점에서 나온 것입니다. 내가 말한 내용에 근본적으로 잘못된 것이 많을 수 있으므로 도움을 요청하는 이유입니다.


* (a|b)*b*c->true제작 규칙 과 같은 것을 고려하지 않는 한 , 규칙에는 유한 상태 오토마타 (예 : 정규식)가 필요합니다. 우리가 방금 말한 것처럼 이것은 의미가 없습니다.


2
공식 문법 과 공식 언어를 혼동 하고 있습니다 . 문법은 언어를 설명 재 작성 규칙의 집합입니다. 언어는 문법으로 설명되는 문자열 집합입니다. 따라서 문법은 정규 표현식의 대안입니다. 언어를 설명하는 방법입니다.
reinierpost 2009 년

@reinierpost이 정보 중 일부를 얻은 대학 강의 노트를 살펴본 후에는 제 실수를 봅니다.
Zwander

처음 시작할 때 혼란을 공유했습니다. 물론 문법도 언어를 형성하므로 정규 표현도 마찬가지입니다. 그러나 공식 언어 이론은 언어의 구문 (형식)을 설명 할 수있는 방법을 연구하는 데 전념하므로 일반적으로 설명하는 내용이 아니라 설명되는 내용에 '언어'라는 용어를 사용합니다.
reinierpost

답변:


24

누구든지 정규 표현식을 사용하여 코드를 구문 분석하는 데 정보가 확산되고 있다고 말한 사람은 누구입니까? 고전적으로 (현대 컴파일러에서는 이것이 어느 정도 사실인지 알지 못합니다) 코드 구문 분석-텍스트에서 구문 트리로 코드 변환은 다음 두 단계로 구성됩니다.

  1. 어휘 분석 : 키워드 , 숫자 상수 , 문자열 , 식별자 등과 같은 원시 텍스트를 청크 로 처리 합니다 . 이것은 결정 론적 유한 오토 마톤 (DFA)과 유사하게 일종의 유한 상태 머신을 사용하여 고전적으로 구현됩니다.

  2. 파서 : 어휘 분석 후 실행하고 원시 텍스트를 주석이 달린 구문 트리로 변환합니다. 프로그래밍 언어의 문법은 (첫 번째 근사치) 컨텍스트가 없으며 (실제로 더 엄격한 하위 집합이 필요함),이를 통해 특정 효율적인 알고리즘이 lexified 코드를 구문 트리로 구문 분석 할 수 있습니다. 이것은 주어진 문자열이 문맥이없는 문법에 속하는지 인식하는 문제 와 유사하지만 , 차이점은 구문 트리의 형태로 증명 을 원한다는 것 입니다.

프로그래밍 언어에 대한 문법은 문맥이없는 문법으로 작성되며,이 표현은 구문 분석기 생성기 에서 빠른 구문 분석기를 구성 하는 데 사용됩니다 . 간단한 예는 일부 비단 말 STATEMENT와 STATEMENT IF-STATEMENT 형식의 규칙을 갖습니다 . 여기서 IF-STATEMENT if CONDITION, BLOCK endif 등 (예 : BLOCK STATEMENT | BLOCK; STATEMENT). 일반적으로 이러한 문법은 BNF (Backus-Naur form)로 지정됩니다.

프로그래밍 언어의 실제 사양은 컨텍스트가 없습니다. 예를 들어 변수가 여러 언어로 선언되지 않은 경우 변수를 표시 할 수 없으며 엄격한 입력 언어를 사용하면 문자열 변수에 정수를 할당하지 못할 수 있습니다. 파서의 임무는 원시 코드를 처리하기 쉬운 형식으로 변환하는 것입니다.

실제로 구문 분석 트리를 생성하지 않지만 구문 분석 할 때 코드를 처리하는 재귀 강하 구문 분석 과 같은 다른 접근법이 있습니다. 트리 생성을 방해하지는 않지만 다른 모든 측면에서 위에서 설명한 것과 동일한 수준으로 작동합니다.


답장을 보내 주셔서 감사합니다. 확실히 몇 가지를 정리했습니다. 또한 훨씬 더 많은 질문을 제기했습니다. 질문에 추가해야합니까, 아니면 여기에 질문해야합니까?
Zwander

5
@Zwander-실제로도 마찬가지입니다. 이 사이트에서는 질문 당 하나의 질문을 작성하기를 원합니다. 토론 포럼이 아닙니다. 질문과 답변 사이트이며 각 질문을 별도의 스레드로 만들고 싶습니다. 이 답변으로 새로운 질문이 제기되면 후속 질문을 조사하는 데 시간을 투자하고 표준 소스에서 답변을 찾을 수 없으면 새 질문을 게시하십시오. (그러나 표준 자원을 먼저 살펴보십시오.)
DW

1
@DW Gotcha, 건배.
Zwander

3
언급 한 두 단계 중 첫 번째 단계는 일반적으로 정규식을 사용하여 수행됩니다. 각 토큰의 형식은 일반적으로 정규식으로 제공됩니다. 이러한 정규식은 단일 DFA로 컴파일 된 다음 DFA가 실제 코드에 적용됩니다.
kasperd

2
@Zwander 재귀 하강 구문 분석은 하나의 구문 분석 기술입니다. 구문 분석 트리를 생성하거나 생성하지 않을 수 있습니다. 일반적으로, 파싱 알고리즘은 프로그램 텍스트에 내재 된 구문 트리를 탐색하기위한 계산 전략을 개발하는 것입니다. 이 구문 / 구문 분석 트리는 컴파일 전략 (단계 수)에 따라 프로세스에서 명시되거나 명시되지 않을 수 있습니다. 그러나 계산 구조에 명시 적이든 암묵적이든 관계없이 궁극적으로 구문 분석 트리의 상향식 탐색이 최소한 하나는 있어야합니다.
babou

12

이것은 고등학교 과제를 위해 무거운 물건입니다.

Yuval Filmus의 답변은 정말 좋습니다. 따라서 그가 작성한 몇 가지 요점을 명확히하기위한 보충적인 답변입니다.

공식 언어는 수학 구조입니다. 프로그래밍 언어에 대한 그들의 사용은 많은 가능한 용도 중 하나 일뿐입니다. 실제로 언어 학자 Noam Chomsky는 공식 ​​언어의 초기 이론에 크게 기여했습니다. 그는 Chomsky Hierarchy를 발명했습니다.형식 언어를 규칙적이고 문맥이없는 등으로 분류합니다. 공식 언어는 영어와 같은 자연 언어의 구문을 설명하기 위해 언어학에도 적용됩니다. 실수로 생각하십시오 : 우리는 실수를 사용하여 로스 앤젤레스에서 뉴욕까지의 거리와 같은 구체적인 것들과 원의 둘레와 지름의 비율과 같은 추상적 인 것들을 설명 할 수 있습니다. 이 두 가지가 실수와 독립적으로 존재하더라도 실수는이를 설명하는 데 유용한 시스템입니다. 공식 언어는 구조적 형식이 비슷하기 때문에 영어와 Python을 모두 설명하는 데 유용한 시스템입니다.

a+b+c=da+b=dcabc 예를 들어, 달러 금액으로 표현하면 방정식에 의미가 있습니다.

일반적으로 프로그래밍 언어에는 두 가지 문법, 즉 어휘 문법과 구문 문법이 있습니다. 어휘 문법은 문자, 세미콜론, 중괄호 및 괄호와 같은 문자를 처리합니다. 일반적으로 정규 문법이므로 정규 표현식이나 DFA 또는 NFA로 표현할 수 있습니다. (공식 언어 이론에는 세 언어가 동일한 수준의 언어를 수용한다는 의미의 증거가 있습니다.) 컴파일러 또는 인터프리터의 어휘 단계는 일반 언어 문법에 대한 미니 인터프리터의 일종입니다. 문법 규칙을 읽고, 그 규칙에 따라 개별 문자를 토큰으로 묶습니다. 예를 들어, 언어에 ifC와 다소 비슷한 문장 이있는 경우 어휘 분석기가 문자를 집중화 할 수 있습니다i 하고 f하나의 토큰으로를IF그런 다음 여는 괄호를 찾아 토큰을 출력 한 OPEN_PAREN다음 괄호 사이의 모든 것을 처리 한 다음 닫는 괄호를 찾아 a를 출력하십시오 CLOSE_PAREN. 어휘 분석기가 토큰을 만들면 토큰이 실제로 프로그래밍 언어의 유효한 문장을 형성하는지 결정하는 파서를 넘겨줍니다. 따라서 ip a == b파이썬으로 작성하면 어휘 분석기는 어떤 종류의 토큰인지 추측하기 위해 최선을 다합니다.ip (아마도 대부분 분석가가 식별자로 가져갈 것 하고 파서에게 전달합니다. 해당 위치의 식별자.

ab 또한 자바의 어휘 및 구문 문법의 예를 가지고있다.

파이썬의 if문장에 대한 문법 규칙을 보자 . 이것이 규칙입니다.

if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]

이 규칙은 구문 분석기가 어휘 분석기에서 전송 된 토큰 문자열이-문인지 어떻게 알아 내는지를 알려줍니다 if. 작은 따옴표로 묶인 단어는 소스 코드에 그와 같이 나타나야 파서가 일반 단어를 찾습니다 if. 파서는 다음의 규칙과 일부 토큰을 일치 시키려고 시도합니다 test.

test: or_test ['if' or_test 'else' test] | lambdef

test문법의 다른 규칙으로 정의됩니다. test정의에 어떻게 포함되어 있는지 주목하십시오 . 이것을 재귀 적 정의라고합니다. 일반 언어에는없는 문맥없는 언어의 큰 힘이며, 프로그래밍 언어 구문에 대해 중첩 루프와 같은 것을 정의 할 수 있습니다.

파서가 일부 토큰과 일치하도록 관리 test하면 콜론 일치를 시도합니다. 성공하면에 대한 규칙을 사용하여 더 많은 토큰을 일치 시키려고 시도합니다 suite. 이 섹션 ('elif' test ':' suite)*은 우리가 리터럴 텍스트를 여러 번 반복 elif하고 그 뒤에 일치하는 것 test, 콜론, 일치하는 것을 반복 할 수 있음을 의미합니다suite . 우리는 또한 제로 반복을 가질 수 있습니다. 끝에 별표는 "0 또는 우리가 원하는만큼"을 의미합니다.

결국은 ['else' ':' suite]입니다. 해당 부분은 대괄호로 묶여 있습니다. 그것은 우리가 0 또는 1을 가질 수 있지만 더 이상은 가질 수 없다는 것을 의미합니다. 이를 일치 시키려면 구문 분석기가 리터럴 텍스트 else, 콜론 및 다음 에 일치해야 합니다 suite. 규칙은 다음과 같습니다 suite.

suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT

기본적으로 C와 유사한 언어의 블록입니다. 파이썬은 줄 바꿈과 들여 쓰기를 사용하여 의미하기 때문에 lexer 출력 NEWLINE, INDENTDEDENT토큰은 파서에게 새 줄이 시작된 위치, 코드가 들여 쓰기 시작된 위치 및 들여 쓰기의 외부 레벨로 돌아간 위치를 파서에게 알려줍니다.

이러한 일치 시도 중 하나라도 실패하면 구문 분석기가 오류를 표시하고 중지합니다. 전체 프로그램의 구문 분석이 성공하면 구문 분석기는 일반적으로 Yuval이 답변에서 다룬 구문 분석 트리와 의미 정보를 저장하는 기호 테이블 및 기타 데이터 구조를 구축합니다. 언어가 정적으로 유형이 지정되면 컴파일러는 구문 분석 트리를 걷고 유형 오류를 찾습니다. 또한 구문 분석 트리를 통해 실제로 실행되는 하위 수준 코드 (어셈블리 언어, Java 바이트 코드, .Net 중급 언어 또는 이와 유사한 코드)를 생성합니다.

연습으로, 친숙한 프로그래밍 언어 ( Python , Java 및 여기 C # , Javascript , C )의 문법을 사용하여 어쩌면 x = a + b;or 같은 간단한 것을 직접 파싱 해 보는 것이 if (True): print("Yay!")좋습니다. 더 간단한 것을 찾고 있다면 JSON 에 대한 멋진 문법도 있습니다.이 문법은 기본적으로 Javascript의 객체 리터럴 구문 (예 :)을 포함합니다 {'a': 1, 'b': 2}. 행운을 빕니다, 이것은 두뇌를 구부리는 물건이지만 미친 마감일이 아닐 때 정말 흥미로운 것으로 판명되었습니다.


나는 여기에 "감사"를 게시하지 않아야한다는 것을 알고 있지만,이 모든 것을 설명하기 위해 시간을내어 응원합니다. "이것은 고등학교 과제를 위해 무거운 물건입니다." 과제의 의도는 정상을 뛰어 넘고 정규 표현에 대해 이야기하는 것이지만 열렬한 컴퓨터 과학 학생으로서 나는 전체 그림을 얻고 싶었습니다. 전체 주제는 매력적입니다.
Zwander

1
@Zwander 저는 방금 대학을 졸업했으며 대부분의 선택 과목은 이와 같은 것들이었습니다. 나는 완전히 혼란 스럽지만 완전히 흡수 된 것을 기억합니다. 또한 이 블로그에 언급 된 컴파일러 디자인에 관한 논문 이나 Michael Sipser 의 저서 ( Theory of Computation )에 대한 저서 와 언어와 계산 론에 관한 John C. Martin의 저서도 좋습니다 . 아마존에서 저렴한 중고 사본을 찾을 수 있습니다. 둘 다 공식 언어 이론을 최대한 간단하게 만듭니다.
tsleyson

10

간단히 말해서

프로그래밍 언어는 프로그램을 문자열로 나타내는 구문과 프로그램의 의도 된 의미 인 의미로 구성됩니다.

공식 언어는 의미없는 구문입니다. 일반적으로 문자열에 의미를 부여하지 않고 공식적으로 정의 된 문자열 세트의 구조를 연구하기위한 것입니다.

정규 표현 및 기타 형식 (예 : 문맥없는 문법)은 공식 언어를 정의하는 데 사용되며 프로그래밍의 구문 구성 요소 및 자연 언어로 사용됩니다. 즉 문장을 구조화 된 방식으로 표현합니다. 이 구조를 프로그래밍 언어의 의미와 관련시키기 위해 다른 메커니즘이 사용됩니다.

특히 자연 언어와 관련하여 많은 부분이 단순화되었습니다.

훨씬 더 자세한 내용

귀하의 질문에 대답하기 위해 처음부터 시작해야합니다. 일반적인 의미의 언어는 비공식적으로 정보 나 아이디어를 전달하는 수단입니다. 언어에서는 일반적으로 구문과 의미를 구별합니다. 의미론은 당신이 말하고 쓰고 싶은 것입니다. 전달하려는 정보. 구문은 전달하기 위해 사용하는 수단, 즉 사람간에, 그리고 이제 사람과 장치간에 또는 장치 (컴퓨터)간에 교환 될 수있는 일반적인 표현입니다.

일반적으로, 당신은 개의 dog아이디어를 전달 하기 위해 단어 를 사용합니다 . 이 단어 dog는 세 글자 또는 동등한 소리로 만들어졌으며 어떤 종류의 동물을 나타 내기위한 것입니다. 핵심 아이디어는 의사 소통이 의사 소통 대상을 표현함으로써 이루어집니다. 표현 구조는 일반적으로 구문이라고하며 표현되는 것을 의미론이라고합니다. 프로그래밍 언어뿐만 아니라 자연어에도 다소 차이가 있습니다.

단어는 다소 기본적인 의미 론적 개념을 나타내는 구문 적 실체입니다. 그러나 이러한 기본 개념은보다 복잡한 의미를 부여하기 위해 다양한 방식으로 결합되어야합니다. 우리 the dog는 특정 개를 의미 the dog bites the cat하고 더 복잡한 아이디어를 전달하기 위해 글 을 씁니다 . 그러나 단어가 구성되는 방식은 규칙에 따라 수정되어야하므로 개와 고양이 중 어느 것이 실제로 다른 것을 물고 있는지 알 수 있습니다.

그래서 우리는 sentence -> subject verb complement문장과 일치하는 규칙을 가지고 있으며 각 부분과 관련된 아이디어가 어떻게 표현되는지 알려줍니다. 이러한 규칙은 구문 표현 규칙으로, 메시지 표현 방식을 알려줍니다. 는 subject자체 규칙에 의해 정의 할 수 있습니다 subject -> article noun등등합니다.

2엑스+1=23엑스123

equation -> expression "=" expression  
expression -> expression "+" expression 
expression -> number

프로그래밍 언어의 구조는 동일합니다. 프로그래밍 언어는 해결해야 할 문제, 이론 증명 또는 동물 간의 우호적 인 관계를 표현하는 것보다 수행 할 계산을 표현하는 데 의미 적으로 특화되어 있습니다. 그러나 이것이 주요 차이점입니다.

구문에 사용되는 표현은 일반적으로 문자열 또는 음성 언어의 소리입니다. 시맨틱은 일반적으로 추상 영역 또는 현실에 속하지만 여전히 우리의 사고 과정이나 장치의 행동 영역에서 추상화됩니다. 통신은 정보 / 아이디어를 신택스로 인코딩하는 것을 수반하며, 이는 수신기에 의해 전송 및 디코딩된다. 그러면 결과는 수신자에 의해 어떤 방식 으로든 해석됩니다.

언어에 대해 우리가 보는 것은 주로 구문과 구조입니다. 위의 예는 구문 문자열과 구조적 구조를 정의하는 가장 일반적인 방법 중 하나 일뿐입니다. 다른 것도 있습니다. 주어진 언어의 경우, 일부 문자열에는 구조가 할당 될 수 있으며 언어에 속한다고 말하지만 다른 문자열에는 그렇지 않습니다.

단어도 마찬가지입니다. 문자 (또는 소리)의 일부 순서는 합법적 인 단어이지만 다른 문자는 그렇지 않습니다.

공식 언어는 의미가없는 구문 일뿐입니다. 알파벳의 기본 요소를 사용하여 시퀀스를 구성 할 수있는 일련의 규칙을 정의합니다. 규칙은 매우 다양하고 때로는 복잡 할 수 있습니다. 그러나 공식 언어는 자연어 프로그래밍 언어에 관계없이 언어 적 의사 소통을 넘어 많은 수학적 목적으로 사용됩니다. 언어로 문자열을 정의하는 규칙 세트를 문법이라고합니다. 그러나 언어를 정의하는 다른 많은 방법이 있습니다.

실제로 언어는 두 가지 수준으로 구성됩니다. 어휘 수준은 알파벳 문자로 구성된 단어를 정의합니다. 구문 수준은 문장 또는 단어의 알파벳 (또는 더 정확하게는 단어 패밀리로 구성되어 유한 알파벳으로 유지됨)으로 구성된 프로그램을 정의합니다. 이것은 반드시 다소 단순화됩니다.

단어의 구조는 대부분의 언어 (프로그래밍 또는 자연어)에서 상당히 단순하므로 일반적으로 가장 간단한 형식 언어 인 일반 언어로 간주되는 언어로 정의됩니다. 정규식 (regexp)으로 정의 할 수 있으며 유한 상태 오토마타라고하는 프로그래밍 된 장치로 쉽게 식별 할 수 있습니다. 프로그래밍 언어의 경우, 단어의 예는 식별자, 정수, 문자열, 실수, 예약어 등이다 if 또는 repeat, 구두점 기호 나 열린 괄호. 단어 패밀리의 예는 식별자, 문자열, 정수입니다.

구문 수준은 일반적으로 단어를 알파벳으로 사용하여 문맥이없는 언어 인 좀 더 복잡한 형식의 언어로 정의됩니다. 위에서 본 규칙은 자연어에 대한 컨텍스트없는 규칙입니다. 프로그래밍 언어의 경우 규칙은 다음과 같습니다.

statement -> assignment
statement -> loop
loop ->  "while" expression "do" statement
assignment -> "identifier" "=" expression
expression -> "identifier"
expression -> "integer"
expression -> expression "operator" expression

이러한 규칙을 사용하면 다음을 작성할 수 있습니다.

while aaa /= bbb do aaa = aaa + bbb / 6 이것은 진술입니다.

그리고 그것이 만들어지는 방식은 구문 분석 트리 또는 구문 트리 (여기서는 완료되지 않음)라는 트리 구조로 표현 될 수 있습니다.

                          statement
                              |
            _______________  loop _______________
           /      /                 \            \
      "while" expression           "do"       statement
       __________|_________                       |
      /          |         \                  assignment
 expression "operator" expression          _______|_______
     |           |          |             /       |       \
"identifier"   "/="   "identifier" "identifier"  "="   expression
     |                      |            |                 |
    aaa                    bbb          aaa             ... ...

규칙 왼쪽에 표시되는 이름은 비 터미널이라고하며 단어는 언어의 알파벳 (어휘 수준 이상)이므로 터미널이라고도합니다. 비 터미널은 프로그램을 구성하는 데 사용할 수있는 다른 구문 구조를 나타냅니다.

이러한 규칙은 컨텍스트가없는 것으로 불립니다. 비 터미널은 표시되는 컨텍스트와 상관없이 해당 규칙을 사용하여 임의로 대체 할 수 있기 때문입니다. 언어를 정의하는 규칙 세트를 문맥없는 문법이라고합니다.

실제로 식별자를 처음 선언해야하거나식이 형식 제한을 충족해야하는 경우에는 제한이 있습니다. 그러나 이러한 제한은 구문 적이 라기보다는 의미 론적이라고 간주 될 수 있습니다. 실제로 일부 전문가들은 정적 의미론 (static semantics) 에 배치합니다 .

어떤 문장, 어떤 프로그램이 주어지면, 그 문장의 의미는이 문장에 대한 구문 분석 트리에 의해 주어진 구조를 분석함으로써 추출됩니다. 따라서 프로그램이 제공 될 때 프로그램에 해당하는 트리 구조를 복구 할 수있는 파서 (parsers)라는 알고리즘을 개발하는 것이 매우 중요합니다.

구문 분석기 앞에는 단어를 인식하고 해당 단어의 계열을 결정하는 어휘 분석기가 있습니다. 그런 다음 기본 트리 구조를 검색하는 구문 분석기에 단어 시퀀스 또는 어휘 요소가 제공됩니다. 이 구조에서 컴파일러는 코드를 생성하는 방법을 결정할 수 있으며, 이는 프로그램의 의미 부분이 컴파일러 측에서 처리됩니다.

컴파일러의 구문 분석기는 실제로 구문 분석 트리에 해당하는 데이터 구조를 빌드하고 컴파일 프로세스의 후반 단계로 전달할 수 있지만 반드시 그럴 필요는 없습니다. 구문 분석 알고리즘을 실행하면 프로그램 텍스트에 내재 된 구문 트리를 탐색하기위한 계산 전략을 개발할 수 있습니다. 이 구문 / 구문 분석 트리는 컴파일 전략 (단계 수)에 따라 프로세스에서 명시되거나 명시되지 않을 수 있습니다. 그러나 계산 구조에 명시 적이든 암묵적이든 관계없이 궁극적으로 파스 트리의 상향식 탐색이 적어도 하나는 필요하다.

그 이유는, 직관적으로, 구문 트리 구조와 관련된 의미론을 정의하는 표준 형식적인 방법은 동종 성 (homomorphism)에 의한 것이기 때문입니다. 큰 말을 두려워하지 마십시오. 아이디어는 단지 전체의 의미를 부품을 연결하는 연산자를 기준으로 부품의 의미에서 구성한다는 것을 고려하는 것입니다.

예를 들어, 문장 the dog bites the cat을 규칙으로 분석 할 수 있습니다 sentence -> subject verb complement. 아는 3 개 하위 트리의 의미 subject, verb그리고 complement그들을 피사체가 행동을하고 있는지, 그리고 고양이가 물린 사람이다라고 우리에게 이야기 구성하는 것이 규칙.

이것은 직관적 인 설명 일 뿐이지 만 공식화 할 수 있습니다. 시맨틱은 구성 요소에서 위쪽으로 구성됩니다. 그러나 이것은 많은 복잡성을 숨 깁니다.

컴파일러의 내부 작업은 여러 단계로 분해 될 수 있습니다. 실제 컴파일러는 중간 표현을 사용하여 단계별로 작동 할 수 있습니다. 일부 단계를 병합 할 수도 있습니다. 이것은 사용되는 기술과 현재 컴파일 언어의 복잡성에 달려 있습니다.


대단하고 도움이되었습니다. 정규식이 토큰 화 프로세스에서 사용된다는 것을 이해합니다 (예 : 문자열 리터럴은 "[^"]*"가장 간단한 형식 으로 정의 하고 이스케이프 문자 등을 무시할 수 있음). 구문 트리 (프로그래밍 언어 측면에서 말하기)를 만드는데도 사용됩니까? 유한 상태 오토마타는 정의상 유한이라고 생각하지 않습니다. 단일 if명령문의 경우에도 구문 트리는 중첩으로 인해 이론적으로 무한 할 수 있습니다. 따라서 유한 상태 오토마타 인 정규식은 구문 트리를 생성 할 목적으로 사용할 수 없습니다.
방랑자

@ Zwander thx 4 편집-정규 표현식의 예가 정확합니다 (예제를 제시해야합니다). BTW, Regex는 또한 문자열 집합의 세계에서 고유 한 의미와 CF (Context-Free ) 구문을 가진 언어입니다. EBNF (Extended BNF)의 단축형을 제외하고는 일반적으로 구문 트리에 사용되는 더 큰 구문을 정의 할 때가 아니라 언어 문자열의 토큰 화에만 사용됩니다. 좀 더 복잡한 형식주의에 어떤 형태로 정규 표현식을 추가해도 대부분의 경우 표현력이 바뀌지 않습니다. 무한대에 대한 당신의 말은 정확하지 않습니다. 다음 의견을 참조하십시오.
babou

@Zwander 모든 형식주의 (공식 언어)는 유한하게 설명되어 있습니다. 이것이 기본 가설입니다. 규칙이 무한한 CF 문법에 관심이 있더라도 규칙의 무한대에 대한 유한 설명을 제공해야합니다. 또한 무한대는 당신에게 트릭을 재생합니다 (공간이 없습니다). if문은 무제한의 (임의의 큰)하지만 항상 유한하다. 유한하게 정의 된 무한 if은입니다 while. CF와 일반의 차이점은 CF는 중첩을 제어 / 허용하지만 정규화는 허용하지 않는다는 것입니다. 그러나 둘 다 유한하게 설명되어 있으며 무제한 문자열을 허용합니다.
babou

1
@Zwander 형식주의는 잘 구성된 문장 (프로그램)을 나타낼 수 있어야하지만 잘 구성된 문장 . 간단히 말해서, FSA는 무제한으로 계산할 수 없습니다. 따라서 닫혀 져야하는 괄호가 몇 개나 열렸는지 알 수 없거나 서로 다른 두 종류의 괄호가 제대로 중첩되지 않습니다. 많은 언어 구조에는 "숨겨진"괄호가 있습니다. 이것은 단순히 구문 검사의 문제가 아니라 의미를 도출하기 위해 적절한 트리 구조를 표현하고 만들 수 없다는 것을 의미합니다. 적절한 트리 구조를 복구하려면 계산을 수행해야합니다.
babou

1
@Zwander 나중에 유용 할 수있는 한 가지 언급은 괄호를 사용하여 트리를 단순히 문자열로 선형화 할 수 있다는 것입니다. 이는 일반적으로 다음과 같은 산술 표현식을 완전히 괄호로 묶을 때 수행하는 작업입니다.(((에이)+)×기음)각 연산자가 적절한 하위 트리 (하위 표현식)를 갖도록합니다. 패시 다운 스택 (푸시 다운 오토마타 참조), 컨텍스트가없는 언어 및 트리 사이에는 밀접한 관계가 있습니다.
babou

2

중요한 차이점이 있습니다. 그중에서 가장 중요한 것은 실제 프로그래밍 언어를 파싱하는 것은 구문 오류 처리에 관한 것입니다. 공식 언어를 사용하면 "언어가 아님"이라고 말하지만 그다지 유용하지 않다고 말하는 컴파일러는 무엇이 잘못되었는지 알려 주어야하며, 작은 오류 인 경우 이상적으로 구문 분석을 수행 할 수 있습니다. 더 많은 오류를보고하십시오. 많은 연구 (및 구현 노력)가 그에 들어갑니다. 따라서 실제 / 거짓 결과에 대해서는 그다지 신경 쓰지 않아도됩니다. 입력의 구조 만 분석하려고합니다. 공식 언어는 도구로 사용되며 겹치는 부분이 많지만 실제로 다른 문제를 해결하고 있습니다.

또한 대부분의 언어에서 문법에 특정 사항을 적용하지 않도록 선택했습니다 ( 예 : "변수가 선언되지 않은 경우 변수를 표시 할 수 없음"). 그것은 일반적으로 파서에 의해 완전히 무시되고 그런 종류의 것을보고 별도의 분석 (의미 적 분석)에 걸리며 문맥 자유와 같은 고려 사항의 영향을받지 않는 것입니다. 그러나 항상 그런 것은 아닙니다-예를 들어 C를 파싱하기 위해 렉서 핵 이 종종 사용되며 C ++은 심각한 의미 론적 분석을 동시에 수행하지 않고는 파싱 할 수없는 언어의 유명한 예입니다 (실제로 C ++을 파싱하는 것은 결정할 수 없습니다. ). 더 간단한 언어에서는 분할되는 경향이 있지만 그렇게하는 것이 더 쉽습니다.


1

공식 언어는 단어 집합입니다. 단어는 알파벳의 기호 문자열입니다.

이것은 생산 규칙과 공식 언어의 결합이 너무 강하다는 것을 의미합니다. 공식 언어가 생산 규칙인지는 올바르지 않습니다. 오히려 생산 규칙은 공식 언어를 정의합니다. 공식 언어는 생산 규칙에 의해 생성 될 수있는 단어입니다. (이렇게하려면 공식 언어가 프로덕션 규칙에 의해 정의 될 수있는 종류 여야합니다. 예를 들어 일반 언어는 컨텍스트 프리 문법으로 정의 할 수 있습니다)

따라서 표현에 해당하는 정규 언어 (a|b)*c*d는 생산 규칙에 의해 정의됩니다.

S->ACd
A->
A->aA
A->bA
C->
C->cC

이러한 생산 규칙이 시작 기호 S에서 생성하는 단어는 정확하게 정규식이 허용하는 문자열입니다.


0

시맨틱과 관련된 정규식과 프로그래밍 언어 사이에는 또 다른 관계가 있습니다. 명령형 언어의 기본 제어 구성은 순차적 구성 (A 및 B 수행), 선택 (A 또는 B 수행) 및 반복 (A 반복)입니다.

동작을 결합하는 동일한 세 가지 방법이 정규식에 있습니다. 서브 루틴 호출을 처리하면 EBNF와 유사합니다.

따라서 정규 표현식의 대수와 명령의 대수 사이에는 많은 유사성이 있습니다. Dijkstra는 "The Three Unification of Three Calculi"에 자세히 설명되어 있습니다. 또한 Milner CCS의 기초이기도합니다.이 질문에 대한 답변을 제공합니다. 병렬 처리를 추가하면 어떻게됩니까?

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