학문적 의미에서 정규 표현은 프로그래밍 언어로 인정됩니까?
호기심에 대한 동기 부여는이다 SO 질문 질문에 난 그냥 보았다 "X를 할 정규식 수 있습니까?" 그리고 그것을 사용하여 가능한 솔루션에 대해 일반적인 의미로 말할 수있는 것이 궁금합니다.
기본적으로 "정규 표현식 튜링이 완료 되었습니까?"
학문적 의미에서 정규 표현은 프로그래밍 언어로 인정됩니까?
호기심에 대한 동기 부여는이다 SO 질문 질문에 난 그냥 보았다 "X를 할 정규식 수 있습니까?" 그리고 그것을 사용하여 가능한 솔루션에 대해 일반적인 의미로 말할 수있는 것이 궁금합니다.
기본적으로 "정규 표현식 튜링이 완료 되었습니까?"
답변:
정규 표현식은 공식 언어 이론에서 "일반 언어"로 알려진 문자열 및 기타 텍스트 정보를 구문 분석하는 데 사용되는 특정 유형의 공식 문법 입니다. 그것들은 프로그래밍 언어가 아닙니다. 그들은 때로는 간헐적으로 보이는 Regex보다 구현하기가 매우 지루하고 혼란 스러울 수있는 코딩의 속기입니다.
프로그래밍 언어는 일반적으로 튜링 완료 언어로 정의됩니다 . 이러한 언어는 계산 가능한 기능 을 처리 할 수 있어야 합니다 . 정규식은이 범주에 맞지 않습니다.
정규식처럼 보이는 언어를 원한다면 J를 사용해보십시오.
토론 참가자가 X 와 Y 의 다른 정의를 사용하는 경우 "is X a Y " 유형의 질문에 대답하기가 어렵습니다 . 일부 정의의 경우 대답은 "예"이고 일부 정의의 경우 대답은 "아니오"일 수 있습니다. 특히 답변 이 다른 정의가 다른 기술적 세부 사항에 의존하는 경우. 또한이 토론에는 잘못된 정보가 포함되어 있으므로 더 긴 답변으로 인내심을 가지십시오.
" 프로그래밍 언어 " 란 무엇을 의미 합니까?
간단한 대답은 "프로그램 작성에 사용되는 언어"일 수 있습니다. 그러나 어떤 종류의 프로그램입니까? 만드는 데 사용할 수있는 언어에 대한 어떤 일부 프로그램의 종류,하지만 프로그램이 아닌 다른 종류의? 다음은 극단적 인 경우를 설명하기위한 두 가지 구체적인 예입니다.
1) M이라는 가상의 언어는 다음과 같이 작동합니다. 프로그램에 단일 문자 "m"이 포함되어 있으면 지뢰 찾기 게임을 만듭니다. 다른 모든 것은 구문 오류입니다.
직관적으로 이것은 "프로그래밍 언어"라고 말하는 것이 아닙니다 . 그러나 M의 마케팅 부서 는 프로그램을 만드는 데 사용될 수 있기 때문에 기술적 으로 정의를 충족 한다고 주장 할 수 있습니다. 물론, 컴파일러는 당신을 위해 중요한 부분을 수행하지만 이것이 컴파일러가하는 일입니까? C 언어의 컴파일러는 간단한 단어를 수십 개의 프로세서 명령어로 변환합니다. M 컴파일러는 더 나아가 작업을 더욱 단순하게 만듭니다.
2) 유명한 Turbo Pascal의 원래 버전을 설치하면 많은 종류의 프로그램을 작성할 수 있습니다. 그러나 필요한 API가 없기 때문에 웹 브라우저에서 실행되는 게임을 작성할 수 없습니다.
그렇다면 터보 파스칼을 프로그래밍 언어로 만드는 것은 무엇입니까?하지만 M에는 없습니다. 간단히 말해서 M보다 Pascal에서 더 많은 것을 할 수 있지만 웹 브라우저에서 Minesweeper 게임을 실행하는 M.NET이 있다고 상상해보십시오. 이제 파스칼이 할 수 있고 M.NET이 할 수없는 것이 있지만, M.NET이 할 수 있고 파스칼이 할 수없는 것도 있습니다. 파스칼의 장점과 M.NET의 장점이 중요하지 않은 이유는 무엇입니까?
정답은 Pascal에서 모든 종류의 알고리즘 을 작성할 수 있지만 M 또는 M.NET에서는 알고리즘 을 작성할 수 없다는 것 입니다. 물론, M은 명령 "m"을 컴파일하고 C는 명령 "strcmp"를 컴파일합니다. 그러나 더 큰 맥락에서 "strcmp"를 넣을 수 있습니다. 예를 들어 두 파일을 한 줄씩 비교하거나 수천 개의 문자열을 읽고 알파벳순으로 정렬하거나 수백만 가지를 정렬 할 수 있습니다. 그리고 프로그래밍 언어의 본질을 만드는 모든 알고리즘 에서 주어진 명령을 사용하는 것이 바로이 기능 입니다.
알고리즘은 정확히 무엇이며, 더 중요한 것은 "모든 알고리즘"이란 무엇입니까? 컴퓨터 과학에서는 Turing-complete 라는 단어를 사용합니다 . 아이디어는 각 언어가 모든 언어를 시뮬레이션 할 수있는 컴퓨터 언어 세트가 있다는 것입니다. 이러한 언어 중 하나는 튜링 기계입니다. 이것이 바로 이런 방식입니다. 파스칼, C, 자바, 파이썬, 리스프, 스몰 토크, XSLT도 있습니다. 우리의 가상 M과 M.NET은 없습니다 . 양질의 컴퓨터 과학 코스를 제공하는 모든 대학에서 더 많은 것을 배울 수 있지만 아이디어는 Turing-complete language가 무엇이든 할 수 있다는 것입니다필요한 최소한의 API를 제공하면 다른 Turing-complete 언어로 할 수 있습니다. (파스칼에 웹 브라우저 API를 제공하면 웹 브라우저에서 모든 종류의 게임을 만들 수 있습니다. 웹 브라우저 API를 M에 제공하면 여전히 지뢰 찾기 만 만들 수 있습니다.) 우리는 은유 적으로 말할 수 있습니다. 프로그래밍 언어에서 모든 API를 제거하면 중요한 것은 남아있는 것입니다.
" 정규 표현식 " 은 무엇을 의미 합니까?
다른 프로그래밍 언어는 약간 다르게 구현합니다. 그러나 원래의 개념은 정규 표현식이 소위 정규 언어를 표현한다는 것이 었습니다 . 여기서는 프로그래밍 언어가 아니라 (의사) 인간 언어에 대해 이야기합니다. "ba", "baba", "bababa"등의 단어로만 구성된 언어를 말하는 이국적인 부족이 있다고 가정 해보십시오. 이 언어를 구두로 "한 번 이상 반복 된 음절 'ba'"또는 정규식을 "(ba) +"로 사용하여 설명 할 수 있습니다.
정규식은 "아무것도", "이 글자", "이것, 그 다음에", "이것 또는 저것", "이것, 한 번 이상 반복됨", "이것이 아님"으로 표현됩니다. 그것은 수학적 정의입니다. 다른 것은 이전 구성 요소에서 만든 편리한 바로 가기입니다. 예를 들어, "이, 두세 번 반복"은 "이 다음에이 다음에 (이것 또는 아무것도 없음)"으로 번역 될 수 있지만 "baba"보다 "ba {2,3}"을 작성하는 것이 더 편리 할 수 있습니다. (ba)? "
실제로 "일반 표현식"의 일반적인 구현은 이보다 더 많은 것을 구현 합니다. 예를 들어, 수학적 정의를 사용하여 "aba", "aabaa", "aaabaaa"등의 언어- "a"와 "b", 같은 수의 "a" "s- 는 일반 언어 가 아닙니다 . 그러나 오늘날 사용되는 많은 "정규 표현식"은 "(a +) b \ 1"로 작성된 "이전에 찾은 것과 같은"추가 개념을 사용하여이를 감지 할 수 있습니다. 이 추가 개념을 사용하여 몇 가지 멋진 작업을 수행 할 수 있습니다 (예 : 소수 의 문자 로 구성된 단어 감지) 아직도, 우리는 어떤 알고리즘도 할 수 없습니다 ... 왜냐하면
원래 주제로 돌아가서 : 정규 표현식 (Chomsky 계층 구조에서 정규 언어를 설명하는 표현식으로 정의되거나 전자와 \ 1 연산으로 정의)이 프로그래밍 언어 (Turing-complete로 정의 됨)입니까? 대답은 ' 아니요' 입니다. 아니, 당신이 구현할 수 있는 알고리즘 정규 표현식을 사용하고 구현할 수 있는 알고리즘은 컴퓨터 과학을 공부하는 사람들은 일반적으로 언어 프로그래밍의 본질로 이해하는 것입니다.
물론 누구나 다른 정의를 주장함으로써 답을 바꿀 수 있습니다 . 처음에 썼 듯이 여기에서 기술적 세부 사항이 중요합니다. 당신이 틀리면 틀린 답을 얻습니다.
당신이하는 경우와 하지 기술적 인 세부 사항에 관심이 대답은 할 수있다 : 당신은 정규 표현식 (그리고 아무것도) 프로그램을 만들 수를 사용할 수 있습니까? 아니요. 왜 프로그래밍 언어라고합니까? (그러나 이와 같은 답변이 여기에서 다운로드되어 삭제 되었으므로이 더 긴 버전을 작성했습니다.)
편집 : 또한 누구나 새로운 기능이 추가 된 "정규 표현식"의 새로운 변형을 구현하는 라이브러리를 만들 수 있습니다. 새로운 기능 으로 인해 전체 시스템이 Turing-complete가되기에 충분할 수 있습니다. 간단한 예는 새로운 구문을 사용하여 Turing-complete 언어를 포함하는 것입니다. 그러나 덜 분명하게 일어날 수도 있습니다. 아마 이미 일어 났을 수도 있습니다.
.Net에서 Regex는 서로 다른 교대 및 둘러보기 조합을 사용하여 여러 형태의 조건을 처리 할 수있을뿐만 아니라 자체 스택을 조작 할 수도 있습니다.
(?xm)
(?>
<(?<Tagname>table)[^>]*>
)
(?(Tagname)
(
</(?(?!\k'Tagname')(?<-Tagname>))*\k'Tagname'>(?<-Tagname>)
|
(?>
<(?<Tagname>[a-z][^\s>]*)[^>]*>
)
|
[^<]+
)+?
(?(Tagname)(?!))
)
예를 들어, 이것은 HTML 테이블을 검색하기 위해 작성한 작은 스 니펫입니다. 다른 정규식 엔진과 달리 캡처 모음 (푸시, 엿보기 및 팝)의 스택을 제어하고 중첩 된 객체를 처리 할 수 있습니다. 더 복잡한 것이 있지만 독점적입니다.
이 예제에서 Regex는 프로그래밍 언어의 모든 기본 요구 사항을 갖는 것으로 볼 수 있다고 생각합니다. 변수, 인라인 메모리, 조건부, 입력 및 출력이 있으며 여러 정규식 컴파일 엔진 중 하나를 사용하여 컴파일합니다 (이 경우 .Net).
정규식으로 HTML을 구문 분석하지 않기 위해 과도하게 사용 된 스 쿼킹에 대한 응답으로 미리 게시 할 수있는 미리 입력 된 응답을 게시했습니다 .HTML 구문 분석
주석 예제 (단지 데모)는 다음과 같습니다.
Function Regex("<(td>)((?:[^<]*(?(?!</\1)<))*)</\1")
Group(0) = "<"
Group(1) = "td>"
Group(0) += Group(1)
Group(2) = LoopMethod()
Group(0) += Group(2)
Group(0) += "</" & Group(1)
Return Group()
End Function
Function LoopMethod()
retGroup = ""
Do
tmpGroup = Everything that is NOT an Opening HTML Delimeter
If the Text following tmpGroup Does NOT Equal "</" & Group(1) Then
tmpGroup += "<"
retGroup += tmpGroup
Else
Exit Do
End If
Loop
Return retGroup
End Function
다시 한 번 HTML 앵무새의 경우 : HTML 구문 분석
이것은 루프와 조건부 (알고리즘?)를 수행하는 간단한 정규식을 보여줍니다. 유일하게 누락 된 것은 실제 수학 계산입니다. 이것은 일반적인 "(. *?)"방법보다 TD 셀을 더 효율적으로 끌어 오는보다 자세한 정규식입니다.
그러나 Regex 애호가이자 스스로를 선포하는 마스터라고해도 Regex가 프로그래밍 언어라고 말하는 사람은 없습니다. 나 자신에 대한 나의 주장은 그것이 혼자서 할 수 없으며 다른 프로그래밍 언어 엔진에 의해 지원되는 동안 자체 엔진을 통해 실행되어야한다는 것입니다.
정규식에서 하나의 찾기 / 바꾸기가 이전 답변에서 설명한 것처럼 Turing-complete 프로그래밍 언어가 아니지만 정규식으로 대체하는 반복 된 조치를 사용할 수 있으면 정규식을 사용하여 모든 Turing 기계를 인코딩 할 수 있습니다.
결과적으로 동일한 검색을 사용하여 계산 가능한 함수를 계산하고 자바 스크립트 정규식을 반복해서 대체 할 수 있습니다.
튜링 완전성을 증명하려면 정규식 검색 / 대체로 튜링 기계를 인코딩하면 충분합니다. 편집기의 상태가 다음과 같다고 가정하십시오.
0000#12345:01-5:0#0000000
리더가있는 기호 테이프로 읽을 수 있습니다.
[left symbols]#[set of states]:[set of symbols]-[current state]:[current symbol]#[right symbols]
상태 5에서 0을 읽고 1을 쓰고 상태를 3으로 변경하고 왼쪽으로 이동하는 규칙의 경우 다음 표기법을 사용하여 추상화합니다.
5:0 => 1, 3:[left]
이전 표기법을 검색 정규식으로 인코딩합니다.
(\d)#(1)(2)(3)(4)(5):(0)(1)-5:0#
그리고 그 대체 표현 (자바 스크립트와 같은)
#12345:01-$4:$1#$8
이제 많은 규칙을 인코딩하는 방법은 무엇입니까? 정규 표현식 검색을 위해 or
연산자 와 연결을 사용 |
하고 그룹 번호를 오프셋과 함께 숫자를 바꿔서 결과를 대체합니다. 예를 들어, 네 가지 규칙 집합을 고려해 봅시다.
5:0 => 1, 3:left
3:0 => 1, 5:right
5:1 => 1, 5:right
3:1 => 1: 3:stop
우리는 그것들을 검색으로 인코딩하고 식을 바꿉니다.
Search:
(\d)#(1)(2)(3)(4)(5):(0)(1)-5:0#|#(1)(2)(3)(4)(5):(0)(1)-3:0#(\d)|#(1)(2)(3)(4)(5):(0)(1)-5:1#(\d)|#(1)(2)(3)(4)(5):(0)(1)-3:1#
Replace by:
$15$23#12345:01-$4$13$21$27:$1$16$24$31#$8
자주 사용하는 자바 스크립트 엔진에서 사용해보십시오.
function turingstep(s) {
return s.replace(/(\d)#(1)(2)(3)(4)(5):(0)(1)-5:0#|#(1)(2)(3)(4)(5):(0)(1)-3:0#(\d)|#(1)(2)(3)(4)(5):(0)(1)-5:1#(\d)|#(1)(2)(3)(4)(5):(0)(1)-3:1#/g,"$15$23#12345:01-$4$13$21$27:$1$16$24$31#$8");
}
var tape = "0000#12345:01-5:0#0000000"
for(var i = 0; i < 6; i++) {
console.log(tape)
tape = turingstep(tape)
}