내 프로그래밍 언어와 그에 대한 컴파일러를 어떻게 만들 수 있습니까?


427

나는 프로그래밍을 철저히하고 BASIC, FORTRAN, COBOL, LISP, LOGO, Java, C ++, C, MATLAB, Mathematica, Python, Ruby, Perl, JavaScript, Assembly 등의 언어를 접했습니다. 사람들이 프로그래밍 언어를 만들고 컴파일러를 고안하는 방법을 이해할 수 없습니다. 또한 사람들이 Windows, Mac, UNIX, DOS 등과 같은 OS를 만드는 방법을 이해할 수 없었습니다. 나에게 신비로운 다른 것은 사람들이 OpenGL, OpenCL, OpenCV, Cocoa, MFC 등과 같은 라이브러리를 만드는 방법입니다. 내가 알아낼 수없는 마지막 것은 과학자들이 마이크로 프로세서를위한 어셈블리 언어와 어셈블러를 고안하는 방법이다. 저는이 모든 것들을 배우고 싶습니다. 저는 15 살입니다. 저는 항상 Babbage, Turing, Shannon 또는 Dennis Ritchie와 같은 컴퓨터 과학자가되고 싶었습니다.


나는 이미 Aho의 컴파일러 디자인과 Tanenbaum의 OS 개념 책을 읽었으며 모두 개념과 코드에 대해서만 높은 수준으로 논의합니다. 세부 사항과 뉘앙스, 컴파일러 또는 운영 체제를 고안하는 방법에 대해서는 다루지 않습니다. 스레드, 세마포어, 프로세스 또는 구문 분석이 무엇인지에 대한 이해가 아니라 자신을 직접 만들 수 있도록 구체적인 이해를 원합니다. 나는 동생에게이 모든 것에 대해 물었다. 그는 MIT EECS의 SB 학생이며 실제 세계에서 이러한 모든 것들을 실제로 만드는 방법에 대한 단서가 없습니다. 그가 아는 ​​것은 여러분이 언급 한 것과 같은 컴파일러 설계 및 OS 개념 (예 : 스레드, 동기화, 동시성, 메모리 관리, 어휘 분석, 중간 코드 생성 등)에 대한 이해입니다.


당신이 유닉스 / 리눅스에 있다면, 당신은 전용 도구에 대한 정보를 얻을 수 있습니다 lex, yacc하고 bison.
mouviciel

나의 첫번째 제안은 Aho의 Dragon Book을 읽는 것입니다. amazon.com/Compilers-Principles-Techniques-Alfred-Aho/dp/…
Julian

1
너무 도움이되지는 않지만 sites.google.com/site/steveyegge2/blog-rants(Steve Yegge의 블로그) 및 steve-yegge.blogspot.com/(Steve Yegge의 다른 블로그)을 방문하는 것이 좋습니다.
KK.

3
가능한 많은 프로그래밍 언어를 배우십시오. 그렇게하면 그들의 개념과 실수를 통해 배울 수 있습니다. 거인의 어깨에 설 수 있는데 왜왜 소음에 만족하십니까?
sbi

1
힌트 : 인터프리터는 컴파일러보다 쉽습니다. 한 줄씩 읽는 입력 텍스트를 기반으로 "무언가를하는"클래스 일뿐입니다. 또 다른 힌트 : 이것을 반영에 연결하면 스크립트로 임의의 객체를 제어 할 수 있습니다.
Dave Cousineau

답변:


407

기본적으로 귀하의 질문은 "컴퓨터 칩, 명령어 세트, 운영 체제, 언어, 라이브러리 및 응용 프로그램은 어떻게 설계되고 구현됩니까?"입니다. 전 세계적으로 수십억 달러 규모의 산업으로 수백만 명의 직원을 고용하고 있으며 그 중 다수는 전문가입니다. 질문에 좀 더 집중하고 싶을 수도 있습니다.

즉, 나는 균열을 일으킬 수 있습니다 :

사람들이 프로그래밍 언어를 만들고 컴파일러를 고안하는 방법을 이해할 수 없습니다.

나에게는 놀랍지 만 많은 사람들이 프로그래밍 언어를 마술처럼 본다. 파티 나 그 밖의 사람들을 만날 때 그들이 무엇을하는지 물어 보면 프로그래밍 언어를 디자인하고 컴파일러와 툴을 구현한다고 말하는데, 사람들-전문 프로그래머, 당신을 염두에 두는 것은 놀라운 일입니다. "와우, 나는 그것에 대해 생각하지 않았지만, 그래, 누군가는 그런 것들을 설계해야한다". 그들은 언어가 이미 도구 인프라로 완전히 형성되었다고 생각한 것과 같습니다.

그들은 단지 나타나지 않습니다. 언어는 다른 제품과 마찬가지로 설계됩니다. 경쟁 가능성 사이에서 일련의 균형을 신중하게 조정합니다. 컴파일러와 도구는 다른 전문 소프트웨어 제품과 같이 빌드됩니다. 문제를 해결하고 한 번에 한 줄의 코드를 작성한 다음 결과 프로그램에서 도대체 테스트하는 것입니다.

언어 디자인은 큰 주제입니다. 언어 설계에 관심이 있다면 시작하기 좋은 곳은 이미 알고있는 언어의 결함이 무엇인지 생각하는 것입니다. 설계 결정은 종종 다른 제품의 설계 결함을 고려하여 발생합니다.

또는 관심이있는 도메인을 고려한 다음 해당 도메인의 문제에 대한 솔루션을 지정하는 DSL (Domain-Specific Language)을 디자인하십시오. 당신은 로고를 언급했다; 이것이 "라인 드로잉"도메인에 대한 DSL의 훌륭한 예입니다. 정규 표현식은 "문자열에서 패턴 찾기"도메인에 대한 DSL입니다. C # / VB의 LINQ는 "데이터 필터링, 결합, 정렬 및 프로젝트"도메인을위한 DSL입니다. HTML은 "페이지의 텍스트 레이아웃 설명"도메인 등을위한 DSL입니다. 언어 기반 솔루션에 적합한 많은 도메인이 있습니다. 내가 가장 좋아하는 것 중 하나는 "텍스트 기반 어드벤처 게임"도메인의 DSL 인 Inform7입니다. 아마도 내가 본 것 중 가장 높은 수준의 심각한 프로그래밍 언어 일 것입니다.

원하는 언어를 스케치 한 후에 는 합법적이고 불법적 인 프로그램을 결정하기위한 규칙이 무엇인지 정확하게 적어보십시오 . 일반적으로 세 가지 수준에서이 작업을 수행하려고합니다.

  1. 어휘 : 언어로 된 단어의 규칙, 합법적 인 문자, 숫자의 모양 등은 무엇입니까?
  2. 구문 : 언어의 단어가 어떻게 더 큰 단위로 결합됩니까? C #에서 더 큰 단위는 표현식, 명령문, 메소드, 클래스 등과 같은 것입니다.
  3. 의미 : 구문 적으로 법적 프로그램 제공, 당신은 어떻게 프로그램이 무엇인지 파악합니까 합니까 ?

가능한 한 정확하게이 규칙 을 기록하십시오 . 그 일을 잘하면 컴파일러 나 해석기를 작성하기위한 기초로 사용할 수 있습니다. C # 사양 또는 ECMAScript 사양을 살펴보고 무슨 뜻인지 확인하십시오. 그들은 법적인 프로그램을 만드는 것이 무엇인지, 어떻게 행동하는지 알아내는 방법을 설명하는 매우 정확한 규칙들로 가득 차 있습니다.

컴파일러 작성을 시작하는 가장 좋은 방법 중 하나는 고급 언어에서 고급 언어로 컴파일러를 작성하는 것입니다. 언어로 된 문자열을 가져 와서 C # 또는 JavaScript 또는 알고있는 언어로 문자열을 뱉어내는 컴파일러를 작성하십시오. 해당 언어의 컴파일러가 언어를 실행 가능한 코드로 바꾸는 작업을 처리하십시오.

C #, VB, VBScript, JavaScript 및 기타 언어 및 도구 디자인에 대한 블로그를 작성합니다. 이 주제에 관심이 있으시면 확인하십시오. http://blogs.msdn.com/ericlippert (기록 자료) 및 http://ericlippert.com (현재)

특히이 게시물이 흥미로울 것입니다. 여기에서는 C # 컴파일러가 의미 분석 중에 수행하는 대부분의 작업을 나열합니다. 보시다시피 많은 단계가 있습니다. 우리는 큰 분석 문제를 개별적으로 해결할 수있는 일련의 문제로 나눕니다.

http://blogs.msdn.com/b/ericlippert/archive/2010/02/04/how-many-passes.aspx

마지막으로, 나이가들 때이 일을하는 직업을 찾고 있다면 대학 인턴으로 Microsoft에 와서 개발자 부서에 들어가는 것을 고려하십시오. 이것이 제가 오늘 직장을 마치는 방법입니다!


CLR이 자동으로 수행 할 수 있으므로 컴파일러 최적화가 더 이상 수행되지 않는 정도에 대해 작성 했습니까?

6
@ Thorbjørn : 용어에 대해 명확하게합시다. "컴파일러"는 한 프로그래밍 언어에서 다른 프로그래밍 언어로 번역되는 모든 장치입니다. C #을 IL로 바꾸는 C # 컴파일러와 IL을 기계 코드로 바꾸는 IL 컴파일러 ( "지터")를 갖는 좋은 점 중 하나는 C # 컴파일러를 IL (쉽게!)로 작성할 수 있다는 것입니다. 프로세서 별 최적화를 지터에 넣습니다. 컴파일러 최적화가 "완료되지 않은"것이 아니라, jit 컴파일러 팀이 우리를 위해 수행하는 것입니다. 참조 blogs.msdn.com/b/ericlippert/archive/2009/06/11/...
에릭 Lippert의에게

6
@ Cyclotis04 : Inform6은 Z 코드로 컴파일되는데, 이는 바이트 코드 기반 가상 머신의 유명한 초기 예입니다. 1980 년대의 모든 Infocom 게임이 메모리보다 크고 여러 아키텍처로 이식 할 수있는 방법입니다. 게임은 z 코드로 컴파일 된 다음 코드 메모리 페이징이있는 z 코드 인터프리터가 여러 컴퓨터에 구현되었습니다. 요즘에는 손목 시계에서 zcode 인터프리터를 실행할 수 있지만 첨단 기술 이 적용된 날에도 가능합니다 . 자세한 내용은 en.wikipedia.org/wiki/Z-machine 을 참조하십시오.
Eric Lippert

@EricLippert Compiler는 장치가 아니며, 장치에는 하드웨어가 포함되어 있습니다. 입력 데이터를 기계 코드로 변환하는 규칙 세트가있는 사전 정의 된 프로그램을 말할 수 있습니다
dharam

2
@dhams : 장치는 특정 목적을 위해 만들어진 것입니다. 내가 작성한 모든 컴파일러는 컴파일러가 존재할 수 있도록 특수 제작 된 하드웨어에서 실행되었습니다.
Eric Lippert

127

Jack Crenshaw의 Lets Build a Compiler 컴파일러와 어셈블리 언어 작성에 대한 흥미로운 소개를 찾을 수 있습니다 .

저자는 매우 간단하게 유지하고 실제 기능을 구축하는 데 중점을 두었습니다.


2
Crenshaw의 소개에서 흥미로운 점은 깨달을 수있는 문제에 부딪 칠 때쯤에 스포일러가 불완전하다는 것입니다. 구현을 시작하기 전에 언어를 완전히 설계해야합니다. 그렇다면 전체 언어 사양을 작성해야한다면, 공식적인 표기법으로 해석하여 파서를 생성하는 도구에 넣을 수있는 이유는 무엇입니까? 그리고 당신은 다른 사람들처럼 그것을하고 있습니다.
kindall

3
@kindall, 당신은 도구를 사용해야하는 이유가 있음을 깨닫기 위해 손으로 그것을해야합니다.

72

" 정말로 배우고 싶습니다". 장기적으로 심각한 경우 :

  • 대학에 가서 소프트웨어 공학을 전공하십시오. 얻을 수있는 모든 컴파일러 클래스를 가져 가라. 수업을 제공하는 사람들은 귀하보다 더 잘 교육 받고 경험이 풍부합니다. 코드를 읽을 수없는 방식으로 정보를 제공하는 데 전문가의 관점을 활용하는 것이 좋습니다.

  • 고등학교를 통해 수학 수업을 고수하고 4 년 동안 대학에서 계속하십시오. 비표준 수학 : 논리, 그룹 이론, 메타 수학에 중점을 둡니다. 이렇게하면 추상적으로 생각하게됩니다. 컴파일에 관한 고급 이론 논문을 읽고 그 이론이 왜 흥미롭고 유용한 지 이해할 수 있습니다. 당신이 영원히 최신 기술 뒤에 있기를 원한다면, 당신은 이러한 고급 이론들을 무시할 수 있습니다.

  • 표준 컴파일러 텍스트 인 Aho / Ullman 등을 수집 / 읽습니다. 여기에는 커뮤니티가 일반적으로 동의하는 것이 기본 사항입니다. 당신은 그 책들에서 모든 것을 사용할 수는 없지만, 그것이 존재한다는 것을 알아야하고, 왜 그것을 사용하지 않는지 알아야합니다. 나는 Muchnick이 훌륭하다고 생각했지만 꽤 고급 주제입니다.

  • 컴파일러를 빌드하십시오. 썩은 것을 만들어 지금 시작하십시오. 이것은 당신에게 몇 가지 문제를 가르쳐 줄 것입니다. 두 번째를 만드십시오. 반복. 이 경험은 당신의 책 학습과 큰 시너지를 만듭니다.

  • 시작하기에 좋은 곳은 BNF (Backus Naur Form), 파서 및 파서 생성기에 대해 배우는 것입니다. BNF는 실제로 컴파일러 랜드에서 보편적으로 사용되며, 모르는 경우 동료 컴파일러 유형과 현실적으로 대화 할 수 없습니다.

컴파일에 대한 첫 번째 소개와 BNF의 직접적인 가치를 문서화뿐만 아니라 도구로 처리 할 수있는 금속 언어로 사용하려면 "메타"컴파일러 (컴파일러를 빌드하는 컴파일러)를 빌드하는 방법에 대한이 자습서 (내 것이 아님)를 참조하십시오 . 의 용지 1964 (네, 바로 읽기) [ "META II 구문 지향 컴파일러 쓰는 언어"발 Schorre에 의해. (http://doi.acm.org/10.1145/800257.808896)]이 IMHO는 지금까지 작성된 최고의 최고의 논문 중 하나입니다. 10 페이지에 컴파일러 컴파일러를 작성하는 방법을 알려줍니다. 나는이 논문에서 처음에 배웠다.

내가 위에서 쓴 것은 개인적인 경험에서 나온 것인데, 그것이 저에게 꽤 도움이되었다고 생각합니다. YMMV이지만 IMHO는별로 없습니다.


54
-1 위의 어느 것도 필요하지 않습니다.
닐 버터 워스

77
@nbt 위의 어느 것도 필요하지 않습니다. 그러나 위의 모든 것이 도움이됩니다. 정말 많이
Konrad Rudolph

1
특히 "추상적으로 생각하는 수학 배우기"에 동의하지 않습니다. 암시. "추상적으로 생각하는 법을 배우는 것"이 ​​자신의 프로그래밍 언어와 컴파일러를 만드는 데 특히 도움이된다고 생각하더라도 (그렇지 않습니다-이 원형 교차로를 가져가는 것보다 믿을 수 없을 정도로 간접적 인 경로를 배우는 것보다 배우는 것이 훨씬 더 유용합니다) 수학은 추상적 인 사고를하는 유일한 분야가 아닙니다! (나는 수학자이다. 그래서 나는 일반적으로 수학의 사용을 부정하지 않고,이 특별한 경우에만 적용 할 수있다 ...)
grautur

26
컴파일러 이론에 대한 고급 기술 문서를 읽으려면 수학적으로 능숙해야합니다. 당신은 그 문헌을 무시하기로 결정할 수 있으며, 따라서 당신의 이론과 따라서 컴파일러는 더 나쁠 것입니다. 여기의 naysayers는 많은 공식 교육없이 컴파일러를 작성할 수 있다고 지적하며 동의합니다. 그들은 당신이 그것없이 정말 좋은 컴파일러를 만들 수 있음을 암시하는 것처럼 보입니다. 그건 내가 걸고 내기하지 않습니다.
Ira Baxter

7
CS는 언어 설계 및 구현에 진정으로 유용한 학문입니다. 물론 필수는 아니지만 활용 해야 할 수십 년의 연구가 있었고 다른 실수를 반복 할 이유가 전혀 없습니다.
Donal Fellows

46

다음 은 컴퓨터 시스템의 요소 : 첫 번째 원칙에서 최신 컴퓨터 구축 이라는 온라인 서적 / 코스입니다 .

시뮬레이터를 사용하면 실제로 처음부터 완전한 컴퓨터 시스템을 구축 할 수 있습니다. 많은 의견 제시 자들이 귀하의 질문이 너무 광범위하다고 언급했지만,이 책은 실제로 관리가 용이 ​​한 상태로 답변합니다. 작업을 마치면 자신의 OS 기능을 사용하는 고급 언어 (사용자가 디자인 한)로 게임을 작성하게되며,이 언어는 컴파일러에 의해 VM 언어 (사용자가 디자인 한)로 컴파일됩니다. VM 변환기가 어셈블리 언어 (사용자가 설계 한 언어)로 번역합니다.이 코드는 어셈블러가 기계 코드 (설계 한)로 어셈블러를 생성합니다.이 코드는 컴퓨터 시스템에서 실행되며 부울 논리를 사용하여 설계 한 칩으로 구성됩니다. 간단한 하드웨어 설명 언어.

챕터 :

  1. 강의 개요
  2. 부울 논리
  3. 조합 칩
  4. 순차적 칩
  5. 기계어
  6. 컴퓨터 아키텍처
  7. 어셈블러
  8. 가상 머신 I : 산술
  9. 가상 머신 II : 제어
  10. 프로그래밍 언어
  11. 컴파일러 I : 구문 분석
  12. 컴파일러 II : 코드 생성
  13. 운영 체제
  14. 아이템 목록

더 재미있는 여행


알 수없는 사람, 수정 해 주셔서 감사합니다. 나는 두 번 시도했지만 설명을 충분히 내 생각에 집중할 수 없었지만 책을 언급하고 싶지 않았습니다. 이 책은 이제 학습 계획 링크 ( www1.idc.ac.il/tecs/plan.html) 에서 온라인으로 제공됩니다 . 온라인에서도 매우 합리적인 가격입니다. 모두를 즐기십시오.
Joe Internet

나는 이것을 나 자신에게 제안하려고했다 ... 게으른 사람을 위해 10 분 소개를 확인하십시오 : NAND에서 Tetris까지 12 단계 @ youtube.com/watch?v=JtXvUoPx4Qs
Richard Anthony Hein

46

물러나 컴파일러는 단순히 한 언어로 된 문서를 다른 언어로 된 문서로 변환하는 프로그램입니다. 두 언어 모두 명확하고 구체적이어야합니다.

언어는 프로그래밍 언어 일 필요는 없습니다. 규칙을 적을 수있는 모든 언어가 될 수 있습니다. 아마 구글 번역을 보셨을 것입니다 ; 그것은 하나의 언어 (예 : 독일어)를 다른 언어 (일본어)로 번역 할 수 있기 때문에 컴파일러입니다.

컴파일러의 또 다른 예는 HTML 렌더링 엔진입니다. 입력은 HTML 파일이고 출력은 화면에 픽셀을 그리는 일련의 지침입니다.

대부분의 사람들이 컴파일러에 대해 이야기 할 때 일반적으로 고급 프로그래밍 언어 (예 : Java, C, Prolog)를 하위 수준 (어셈블리 또는 기계 코드)으로 변환하는 프로그램을 말합니다. 어려울 수 있습니다. 그러나 컴파일러가 한 언어를 다른 언어로 번역하는 프로그램이라는 일반적인 관점으로 볼 때 그리 나쁘지 않습니다.

문자열의 모든 단어를 바꾸는 프로그램을 작성할 수 있습니까? 예를 들면 다음과 같습니다.

When the cat's away, the mice will play.

된다

nehW eht s'tac yawa, eht ecim lliw yalp.

작성하기 어려운 프로그램은 아니지만 몇 가지 사항을 고려해야합니다.

  • "단어"란 무엇입니까? 단어를 구성하는 문자를 정의 할 수 있습니까?
  • 말은 어디에서 시작하고 끝나나요?
  • 단어가 한 칸만 분리되어 있거나 더 많거나 적을 수 있습니까?
  • 구두점도 바꿔야합니까?
  • 단어 안의 문장 부호는 어떻습니까?
  • 대문자는 어떻게 되나요?

이 질문에 대한 답은 언어를 잘 정의하는 데 도움이됩니다. 이제 프로그램을 작성하십시오. 축하합니다. 방금 컴파일러를 작성했습니다.

어떻습니까 : 일련의 그리기 지시를 받아 PNG (또는 JPEG) 파일을 출력하는 프로그램을 작성할 수 있습니까? 아마도 이런 식으로 뭔가 :

image 100 100
background black
color red
line 20 55 93 105
color green
box 0 0 99 99

다시 말하지만, 언어를 정의하기 위해 약간의 생각을해야합니다.

  • 기본 지침은 무엇입니까?
  • "라인"이라는 단어 뒤에 오는 것은 무엇입니까? "색상"뒤에 무엇이 나오는가? "배경", "상자"등에 대해서도 마찬가지입니다.
  • 숫자는 무엇입니까?
  • 빈 입력 파일이 허용됩니까?
  • 단어를 대문자로 입력해도 괜찮습니까?
  • 음수가 허용됩니까?
  • "이미지"지시문을 제공하지 않으면 어떻게됩니까?
  • 색상을 지정하지 않아도 괜찮습니까?

물론 더 많은 질문에 대답 할 수 있지만 문제를 해결할 수 있으면 언어를 정의한 것입니다. 번역을하기 위해 작성한 프로그램은 컴파일러라고 생각합니다.

알다시피, 컴파일러 작성은 그리 어렵지 않습니다. Java 또는 C에서 사용한 컴파일러는이 두 예제 중 더 큰 버전입니다. 그러니 가자! 간단한 언어를 정의하고 해당 언어로 작동하도록 프로그램을 작성하십시오. 조만간 언어를 확장하고 싶을 것입니다. 예를 들어 변수 또는 산술 표현식을 추가 할 수 있습니다. 컴파일러는 더 복잡해 지지만 직접 작성했기 때문에 모든 것을 이해할 수 있습니다. 그것이 언어와 컴파일러 방식입니다.


7
myFirstCompiler = (str)-> ( ""+ (str || "")). split ( ''). reverse (). join ( ''); jsfiddle.net/L7qSr
래리 배틀

21

컴파일러 디자인에 관심이 있다면 Dragon Book (공식 제목 : 컴파일러 : 원칙, 기술 및 도구)을 확인하십시오. 이 주제에 대한 고전적인 책으로 널리 알려져 있습니다.


4
이 책을 최대한 활용하려면 약간의 실제 경험이 필요할 수 있습니다. 그래도 훌륭한 참조입니다.

13
-1이 책을 읽지 않은 사람 만이 드래곤 북이 좋다고 생각할 수 있습니다. 특히 문제를 다루지 않습니다.
Neil Butterworth

33
드래곤 북? 열 다섯 살짜리 아이를 위해? 차라리 그의 열정을 좀 더 오래 유지하고 싶다.
David Thornley

1
좀 더 접근하기 쉬운 대안 : '프로그래밍 언어 실용 학'3e .
willjcroz 2016 년

@DavidThornley 그를 완전히 계산하지 마십시오 (예, 이것은 매우 오래된 게시물임을 알고 있습니다). 나는 15 세에 언어가 어떻게 작동하는지 연구하기 시작했고 가상 머신에 특별히 집중했습니다. 이제 저는 16 살이고 몇 달 동안 연구, 쓰기, 재 작성을 해본 결과 통역사와 컴파일러가 마음에 들었습니다.
David


10

컴파일러 나 OS에 마법이 있다고 믿지 마십시오. 모든 모음을 문자열로 세거나 배열에 숫자를 더하기 위해 작성한 프로그램을 기억하십니까? 컴파일러는 개념 상 다르지 않습니다. 그것은 훨씬 더 크다.

모든 프로그램에는 세 단계가 있습니다 :

  1. 물건을 읽으십시오
  2. 그 물건을 처리 : 입력 데이터를 출력 데이터로 변환
  3. 다른 자료를 작성하십시오 – 출력 데이터

생각해보십시오 : 컴파일러에 입력되는 것은 무엇입니까? 소스 파일의 문자열

컴파일러의 출력은 무엇입니까? 대상 컴퓨터에 대한 기계 명령어를 나타내는 바이트 문자열.

그렇다면 컴파일러의 "프로세스"단계는 무엇입니까? 그 단계는 무엇을합니까?

다른 프로그램처럼 - - 컴파일러가 있음을 고려하는 경우 이러한 세 단계를 포함하는, 당신은 컴파일러의 구축 방법에 대한 좋은 생각을해야합니다.


3
Neil이 말했듯이 사실이지만 유용하지는 않습니다. 재귀 문법 및 기호 테이블과 같은 기본 컴파일러 측면은 직관적으로 명확하지 않습니다.
메이슨 휠러

1
@Mason Wheeler : 컴파일러를 작성하고 (목표 언어를 설계 할까?) 현실적으로 꿈꾸는 사람이라면 재귀 문법기호 테이블 이 매우 기본적인 개념 이라고 생각할 것 입니다.
FumbleFingers 2018 년

8

나는 전문가가 아니지만 여기에 내 찌르기가 있습니다.

컴파일러 작성에 대해 묻지 않고 단지 어셈블러입니다. 이것은 실제로 마술이 아닙니다.

SO ( https://stackoverflow.com/questions/3826692/how-do-i-translate-assembly-to-binary ) 에서 다른 사람의 답변을 훔치면 어셈블리는 다음과 같습니다.

label:  LDA #$00
        JMP label

그런 다음 어셈블러를 통해 실행하고 다음과 같이 바꿉니다.

$A9 $00
$4C $10 $00

다음과 같이 모두 뭉개졌습니다.

$A9 $00 $4C $10 $00

정말 마술이 아닙니다.

메모장은 16 진수가 아닌 ASCII를 사용하기 때문에 메모장에 쓸 수 없습니다. 16 진 편집기를 사용하거나 단순히 프로그래밍 방식으로 바이트를 작성합니다. 16 진수를 파일에 쓰고 이름을 "a.exe"또는 "a.out"으로 지정한 다음 OS에게 파일을 실행하도록 지시하십시오.

물론 최신 CPU와 운영 체제는 매우 복잡하지만 기본 아이디어입니다.

새 컴파일러를 작성하려면 다음을 수행하십시오.

1) pyparsing (또는 다른 좋은 파싱 프레임 워크)의 계산기 예제와 같은 것을 사용하여 해석 언어를 작성하십시오. 구문 분석의 기본 사항을 빠르게 익힐 수 있습니다.

2) 번역기를 작성하십시오. 언어를 Javascript로 번역하십시오. 이제 언어가 브라우저에서 실행됩니다.

3) LLVM, C 또는 Assembly와 같은 낮은 레벨에 번역기를 작성하십시오.

여기서 멈출 수 있습니다. 이것은 컴파일러입니다. 최적화 컴파일러는 아니지만 문제는 아닙니다. 링커와 어셈블러 작성을 고려해야 할 수도 있지만 정말로 원하십니까?

4) (Insane) 옵티 마이저를 작성하십시오. 대규모 팀이이 작업에 수십 년 동안 노력하고 있습니다.

4) (Sane) 기존 커뮤니티에 참여하십시오. GCC, LLVM, PyPy, 모든 통역사에서 일하는 핵심 팀.


8

몇몇 다른 사람들은 훌륭한 대답을했습니다. 몇 가지 제안을 더 추가하겠습니다. 먼저, 당신이하려는 일에 대한 좋은 책은 Appel의 Modern Compiler Implementation 텍스트입니다 ( C , Java 또는 Standard ML 중에서 선택하십시오 ). 이 책은 최소한의 런타임 지원 라이브러리와 함께 에뮬레이터에서 실행될 수있는 간단한 언어 Tiger에서 MIPS 어셈블리에 대한 컴파일러의 완전한 구현을 안내합니다. 컴파일 된 언어가 작동하는 데 필요한 모든 것을 한 번에 통과하려면 꽤 좋은 책 1 입니다.

Appel은 사전 디자인 된 언어를 컴파일하는 방법을 안내하지만 다양한 언어 기능이 무엇을 의미하는지 또는 자신의 디자인에 대한 상대적인 장점으로 생각하는 방법에 많은 시간을 소비하지 않습니다. 이러한 측면에서 프로그래밍 언어 : 개념 및 구성 은 괜찮습니다. 컴퓨터 프로그래밍의 개념, 기법 및 모델은 단일 언어 ( Oz ) 와 관련하여 언어 디자인에 대해 깊이 생각하기에 좋은 책입니다 .

마지막으로 Appel에 C, Java 및 Standard ML로 된 텍스트가 있다고 언급했습니다. 컴파일러 구성 및 프로그래밍 언어에 대해 진지한 경우 ML을 배우고 해당 버전의 Appel을 사용하는 것이 좋습니다. ML 계열 언어에는 강력한 유형 시스템이 주로 기능적입니다. 다른 언어와는 다른 기능이므로 기능 언어를 모르는 경우 학습하면 언어 기술이 연마됩니다. 또한 패턴 일치 및 기능적 사고 방식은 컴파일러에서 자주 수행해야하는 조작 유형에 매우 적합하므로 ML 기반 언어로 작성된 컴파일러는 일반적으로 C로 작성된 컴파일러보다 훨씬 짧고 이해하기 쉽습니다. 자바 또는 유사한 언어. 하퍼의 책Standard ML은 시작하기에 좋은 안내서입니다. 이를 통해 Appel의 표준 ML 컴파일러 구현 책을 준비해야합니다. Standard ML을 배우면 나중에 작업하기 위해 OCaml을 쉽게 선택할 수 있습니다. IMO는 작업 프로그래머를 위해 더 나은 툴링을 제공합니다 (주변 OS 환경과 더 깨끗하게 통합되고 실행 프로그램을 쉽게 생성하며 ulex 및 Menhir와 같은 멋진 컴파일러 작성 도구가 있음).


1 장기 참고를 위해, 나는 파서 알고리즘의 내부 작동과 같은 다른 것들에 대한 더 자세한 내용을 가지고 있지만 Appel의 책은 매우 훌륭하기 때문에 Dragon Book을 선호합니다. 첫 번째 패스. 기본적으로 Appel은 컴파일러를 통해 전체 작업을 수행하는 한 가지 방법을 가르쳐주고이를 안내합니다. Dragon Book은 다양한 디자인 대안을보다 자세하게 다루고 있지만 무언가를 작동시키는 방법에 대한 지침은 훨씬 적습니다.


편집 : 잘못된 Aho 참조를 Sethi로 대체하십시오 (CTMCP 언급).


대학 통역 수업을 위해 프로그래밍 언어의 필수 요소가있었습니다. 그것은 끔찍했다. 나는 심지어 개인적으로 체계를 좋아하고 구문을 신경 쓰지 않습니다. 저에게 그것을 파괴 한 개념에 대한 잘못된 설명이었습니다.
Greg Guida

나는 Appel이 계속해서 편집하는 것을 좋아하지만 그의 책은 많은 사전 지식을 가지고 있다고 생각했습니다.
Jon Harrop

6

대학에서 수업을위한 컴파일러를 만들어야했습니다.

이 작업을 수행하기위한 기본 사항은 생각만큼 복잡하지 않습니다. 첫 번째 단계는 문법을 만드는 것입니다. 영어 문법을 생각하십시오. 같은 방식으로 주제와 술어가있는 문장을 구문 분석 할 수 있습니다. 이에 대한 자세한 내용은 Context Free Grammars 에 대해 읽으십시오 .

문법이 다운되면 (언어의 규칙), 컴파일러 작성은 이러한 규칙을 따르는 것만 큼 간단합니다. 컴파일러는 일반적으로 머신 코드로 번역되지만 x86을 배우고 싶지 않다면 MIPS를 보거나 직접 가상 머신을 만드는 것이 좋습니다.

컴파일러에는 일반적으로 스캐너와 파서의 두 부분이 있습니다. 기본적으로 스캐너는 코드를 읽고이를 토큰으로 분리합니다. 파서는 해당 토큰의 구조를 살펴 봅니다. 그런 다음 컴파일러는 약간의 간단한 규칙을 따라 필요한 코드 (어셈블리, 바이트 코드와 같은 중간 코드 등)로 변환합니다. 더 작고 작은 조각으로 나누면 결국 겁이 나지 않습니다.

행운을 빕니다!


8
개념적으로 간단합니까? 예. 실제로 간단합니까? 호
닐 버터 워스

7
음. 스캔 / 파싱 후 컴파일러는 유형 검사 / 유추, 최적화, 레지스터 할당 등을 수행해야합니다.이 단계는 간단합니다. (해석 된 코드를 사용할 때는 이러한 부분을 런타임 단계로 연기하기 만하면됩니다.)
Macke

컴파일러는 두 가지 기본 부분을 가지고 있지만 그중 하나는 프로그램에 대한 추상 설명 (일반적으로 스캔 및 파싱으로 나뉩니다)을 작성하고 다른 하나는 일부 추상 설명의 버전을 다시 작성하는 것입니다 다른 형식 (예 : 기계 코드). (측면 참고 사항 : 컴파일러 최적화는 일반적으로 작성하기 전에 추상 설명을 개선하려고 시도하지만 개선 된 것입니다.)
Donal Fellows

6

Petzold의 Book Code 는 첫 번째 원칙부터 비 기술자 및 기술자에게 모두 훌륭한 소개입니다. 너무 많이 읽지 않으면 서 읽기 쉽고 광범위합니다.

이제 이것을 작성 했으므로 다시 읽어야합니다.



5

이 스레드에는 훌륭한 답변이 있지만, 같은 질문을 한 적이 있기 때문에 내 것을 추가하고 싶었습니다. (또한 Joe-Internet이 제안한 책이 훌륭한 자료임을 지적하고 싶습니다.)

먼저 컴퓨터가 어떻게 작동 하는가에 대한 질문입니다. 방법은 다음과 같습니다. 입력-> 계산-> 출력.

먼저 "계산"부분을 고려하십시오. 입력 및 출력이 나중에 어떻게 작동하는지 살펴 보겠습니다.

컴퓨터는 기본적으로 프로세서 (또는 CPU)와 일부 메모리 (또는 RAM)로 구성됩니다. 메모리는 각각 유한 비트 수를 저장할 수있는 위치의 모음이며, 이러한 각 메모리 위치 자체는 숫자로 참조 될 수 있으며이를 메모리 위치의 주소라고합니다. 프로세서는 데이터를 가져올 수있는 가제트입니다. 메모리에서 데이터를 기반으로 일부 작업을 수행하고 일부 데이터를 메모리에 다시 기록합니다. 프로세서는 메모리에서 데이터를 읽은 후 무엇을 읽고 무엇을해야하는지 어떻게 알 수 있습니까?

이에 대한 답을 얻으려면 프로세서의 구조를 이해해야합니다. 다음은 상당히 간단한 견해입니다. 프로세서는 기본적으로 두 부분으로 구성됩니다. 하나는 프로세서 내부에 작동 메모리 역할을하는 메모리 위치 세트입니다. 이것을 "레지스터"라고합니다. 두 번째는 레지스터의 데이터를 사용하여 특정 작업을 수행하도록 설계된 전자 장치입니다. "프로그램 카운터"또는 PC라는 두 개의 특수 레지스터와 "명령 레지스터"또는 ir가 있습니다. 프로세서는 메모리가 세 부분으로 분할 된 것으로 간주합니다. 첫 번째 부분은 실행중인 컴퓨터 프로그램을 저장하는 "프로그램 메모리"입니다. 두 번째는“데이터 메모리”입니다. 세 번째는 특별한 목적으로 사용되므로 나중에 이야기하겠습니다. 프로그램 카운터에는 프로그램 메모리에서 읽을 다음 명령어의 위치가 포함되어 있습니다. 명령 카운터에는 현재 수행중인 작업을 나타내는 숫자가 들어 있습니다. 프로세서가 수행 할 수있는 각 작업은 작업의 opcode라고하는 숫자로 참조됩니다. 컴퓨터가 본질적으로 작동하는 방식은 프로그램 카운터가 참조하는 메모리 위치를 명령어 레지스터로 읽어들이는 것입니다 (그리고 프로그램 카운터를 증가시켜 다음 명령어의 메모리 위치를 가리킴). 다음으로 명령 레지스터를 읽고 원하는 작업을 수행합니다. 예를 들어 명령은 특정 메모리 위치를 레지스터로 읽거나 일부 레지스터에 쓰거나 두 레지스터의 값을 사용하여 일부 작업을 수행하고 출력을 세 번째 레지스터에 쓰도록 할 수 있습니다. 명령 카운터에는 현재 수행중인 작업을 나타내는 숫자가 들어 있습니다. 프로세서가 수행 할 수있는 각 작업은 작업의 opcode라고하는 숫자로 참조됩니다. 컴퓨터가 본질적으로 작동하는 방식은 프로그램 카운터가 참조하는 메모리 위치를 명령어 레지스터로 읽어들이는 것입니다 (그리고 프로그램 카운터를 증가시켜 다음 명령어의 메모리 위치를 가리킴). 다음으로 명령 레지스터를 읽고 원하는 작업을 수행합니다. 예를 들어 명령은 특정 메모리 위치를 레지스터로 읽거나 일부 레지스터에 쓰거나 두 레지스터의 값을 사용하여 일부 작업을 수행하고 출력을 세 번째 레지스터에 쓰도록 할 수 있습니다. 명령 카운터에는 현재 수행중인 작업을 나타내는 숫자가 들어 있습니다. 프로세서가 수행 할 수있는 각 작업은 작업의 opcode라고하는 숫자로 참조됩니다. 컴퓨터가 본질적으로 작동하는 방식은 프로그램 카운터가 참조하는 메모리 위치를 명령어 레지스터로 읽어들이는 것입니다 (그리고 프로그램 카운터를 증가시켜 다음 명령어의 메모리 위치를 가리킴). 다음으로 명령 레지스터를 읽고 원하는 작업을 수행합니다. 예를 들어 명령은 특정 메모리 위치를 레지스터로 읽거나 일부 레지스터에 쓰거나 두 레지스터의 값을 사용하여 일부 작업을 수행하고 출력을 세 번째 레지스터에 쓰도록 할 수 있습니다. 프로세서가 수행 할 수있는 각 작업은 작업의 opcode라고하는 숫자로 참조됩니다. 컴퓨터가 본질적으로 작동하는 방식은 프로그램 카운터가 참조하는 메모리 위치를 명령어 레지스터로 읽어들이는 것입니다 (그리고 프로그램 카운터를 증가시켜 다음 명령어의 메모리 위치를 가리킴). 다음으로 명령 레지스터를 읽고 원하는 작업을 수행합니다. 예를 들어 명령은 특정 메모리 위치를 레지스터로 읽거나 일부 레지스터에 쓰거나 두 레지스터의 값을 사용하여 일부 작업을 수행하고 출력을 세 번째 레지스터에 쓰도록 할 수 있습니다. 프로세서가 수행 할 수있는 각 작업은 작업의 opcode라고하는 숫자로 참조됩니다. 컴퓨터가 본질적으로 작동하는 방식은 프로그램 카운터가 참조하는 메모리 위치를 명령어 레지스터로 읽어들이는 것입니다 (그리고 프로그램 카운터를 증가시켜 다음 명령어의 메모리 위치를 가리킴). 다음으로 명령 레지스터를 읽고 원하는 작업을 수행합니다. 예를 들어 명령은 특정 메모리 위치를 레지스터로 읽거나 일부 레지스터에 쓰거나 두 레지스터의 값을 사용하여 일부 작업을 수행하고 출력을 세 번째 레지스터에 쓰도록 할 수 있습니다. 컴퓨터가 본질적으로 작동하는 방식은 프로그램 카운터가 참조하는 메모리 위치를 명령어 레지스터로 읽어들이는 것입니다 (그리고 프로그램 카운터를 증가시켜 다음 명령어의 메모리 위치를 가리킴). 다음으로 명령 레지스터를 읽고 원하는 작업을 수행합니다. 예를 들어 명령은 특정 메모리 위치를 레지스터로 읽거나 일부 레지스터에 쓰거나 두 레지스터의 값을 사용하여 일부 작업을 수행하고 출력을 세 번째 레지스터에 쓰도록 할 수 있습니다. 컴퓨터가 본질적으로 작동하는 방식은 프로그램 카운터가 참조하는 메모리 위치를 명령어 레지스터로 읽어들이는 것입니다 (그리고 프로그램 카운터를 증가시켜 다음 명령어의 메모리 위치를 가리킴). 다음으로 명령 레지스터를 읽고 원하는 작업을 수행합니다. 예를 들어 명령은 특정 메모리 위치를 레지스터로 읽거나 일부 레지스터에 쓰거나 두 레지스터의 값을 사용하여 일부 작업을 수행하고 출력을 세 번째 레지스터에 쓰도록 할 수 있습니다.

이제 컴퓨터는 어떻게 입출력을 수행합니까? 매우 간단한 답변을 드리겠습니다. 참조 http://en.wikipedia.org/wiki/Input/output http://en.wikipedia.org/wiki/Interrupt. 이상. 메모리의 세 번째 부분과 인터럽트라는 것을 사용합니다. 컴퓨터에 연결된 모든 장치는 프로세서와 데이터를 교환 할 수 있어야합니다. 앞에서 언급 한 메모리의 세 번째 부분을 사용합니다. 프로세서는 각 장치에 메모리 슬라이스를 할당하고 장치와 프로세서는 해당 메모리 슬라이스를 통해 통신합니다. 그러나 프로세서는 장치가 데이터를 교환해야하는 위치와 장치를 나타내는 위치를 어떻게 알 수 있습니까? 여기에서 인터럽트가 발생합니다. 인터럽트는 기본적으로 프로세서가 현재 상태를 일시 중지하고 모든 레지스터를 알려진 위치에 저장 한 다음 다른 작업을 시작하라는 신호입니다. 많은 인터럽트가 있으며 각 인터럽트는 고유 번호로 식별됩니다. 각 인터럽트마다 특별한 프로그램이 있습니다. 인터럽트가 발생하면 프로세서는 인터럽트에 해당하는 프로그램을 실행합니다. 이제 BIOS와 하드웨어 장치가 컴퓨터 마더 보드에 연결되는 방식에 따라 모든 장치에 고유 한 인터럽트와 메모리 조각이 제공됩니다. BIOS의 도움으로 운영 체제를 부팅하는 동안 각 장치의 인터럽트 및 메모리 위치를 결정하고 인터럽트를 통해 장치를 올바르게 처리하기위한 특수 프로그램을 설정합니다. 따라서 장치에 데이터가 필요하거나 데이터를 보내려고 할 때 인터럽트 신호를 보냅니다. 프로세서가 수행중인 작업을 일시 중지하고 인터럽트를 처리 한 다음 수행중인 작업으로 돌아갑니다. hdd, 키보드 등과 같은 많은 종류의 인터럽트가 있습니다. 중요한 것은 시스템 타이머입니다. 시스템 타이머는 일정한 간격으로 인터럽트를 호출합니다. 또한 소프트웨어 인터럽트라고하는 인터럽트를 트리거 할 수있는 opcode가 있습니다.

이제 우리는 운영 체제의 작동 방식을 거의 이해할 수 있습니다. 부팅 할 때 os는 타이머 인터럽트를 설정하여 일정한 간격으로 os를 제어 할 수 있습니다. 또한 다른 장치 등을 처리하기 위해 다른 인터럽트를 설정합니다. 이제 컴퓨터가 많은 프로그램을 실행하고 타이머 인터럽트가 발생하면 os 게인 제어가 발생하고 프로세스 관리, 메모리 관리 등과 같은 중요한 작업을 수행합니다. 프로그램이 장치에 직접 액세스하지 않고 하드웨어 장치에 액세스하는 추상적 인 방법. 프로그램이 장치에 액세스하려고 할 때, os가 제공 한 일부 코드를 호출 한 다음 장치와 통신합니다. 동시성, 스레드, 잠금, 메모리 관리 등을 다루는 많은 이론이 있습니다.

이제 이론적으로 opcode를 사용하여 직접 프로그램을 작성할 수 있습니다. 이것이 기계 코드입니다. 이것은 분명히 매우 고통 스럽습니다. 이제 프로세서의 어셈블리 언어는 이러한 opcode의 니모닉 일 뿐이므로 프로그램을보다 쉽게 ​​작성할 수 있습니다. 간단한 어셈블러는 어셈블리로 작성된 프로그램을 가져와 니모닉을 적절한 opcode로 대체하는 프로그램입니다.

프로세서 및 어셈블리 언어를 설계하는 방법은 무엇입니까? 컴퓨터 아키텍처에 관한 책을 읽어야한다는 것을 알기 위해. (joe-internet이 참조한이 책의 1-7 장 참조). 여기에는 부울 대수, 간단한 조합 회로를 추가, 곱하기 등을 만드는 방법, 메모리 및 순차 회로를 만드는 방법, 마이크로 프로세서를 만드는 방법 등이 포함됩니다.

이제 어떻게 컴퓨터 언어를 쓰는가? 기계어 코드로 간단한 어셈블러를 작성하여 시작할 수 있습니다. 그런 다음 해당 어셈블러를 사용하여 C의 간단한 하위 집합에 대한 컴파일러를 작성하십시오. 그런 다음 C의 해당 하위 집합을 사용하여보다 완전한 C 버전을 작성하십시오. 마지막으로 C를 사용하여 Python 또는 C ++와 같은 더 복잡한 언어를 작성하십시오. 물론 언어를 작성하려면 먼저 언어를 설계해야합니다 (프로세서를 원하는 방식과 동일). 다시 한 번 교과서를 살펴보십시오.

그리고 어떻게 OS를 작성합니까? 먼저 x86과 같은 플랫폼을 대상으로합니다. 그런 다음 부팅 방법과 OS 호출시기를 파악합니다. 일반적인 PC는 이런 식으로 부팅됩니다. 시작되고 bios가 몇 가지 테스트를 수행합니다. 그런 다음 BIOS는 HDD의 첫 번째 섹터를 읽고 내용을 메모리의 특정 위치에로드합니다. 그런 다음이로드 된 데이터의 실행을 시작하도록 CPU를 설정합니다. 이것은 당신이 운영하는 지점입니다. 이 시점에서 일반적인 OS는 나머지 자체 메모리를로드합니다. 그런 다음 장치를 초기화하고 다른 것을 설정하고 마지막으로 로그인 화면으로 인사합니다.

따라서 운영 체제를 작성하려면 "부트 로더"를 작성해야합니다. 그런 다음 인터럽트 및 장치를 처리하는 코드를 작성해야합니다. 그런 다음 프로세스 관리, 장치 관리 등을위한 모든 코드를 작성해야합니다. 그런 다음 OS에서 실행중인 프로그램이 장치 및 기타 리소스에 액세스 할 수 있도록 API를 작성해야합니다. 마지막으로 디스크에서 프로그램을 읽고 프로세스로 설정하고 실행하기 시작하는 코드를 작성해야합니다.

물론 내 대답은 명백히 단순화되었으며 아마도 거의 사용되지 않을 것입니다. 내 변호에서 나는 이론적으로 대학원생이기 때문에 많은 것들을 잊어 버렸습니다. 그러나 많은 것들을 구글로 검색하고 더 많은 것을 찾을 수 있습니다.


4

나는 당신과 비슷한 혼란 상태에 있었을 때 프로그래밍 경력의 요점을 기억할 수 있습니다 : 나는 이론, 드래곤 북, 타이거 북 (빨간색)을 꽤 많이 읽었지만 여전히 많이 읽지 못했습니다. 그것을 모두 모으는 방법에 대한 단서.

무엇 함께 묶어 않은 것은 할 수있는 구체적인 프로젝트 발견되었다 할을 (I은 모든 이론의 작은 부분 집합이 필요하다고 찾는 다음과).

Java VM은 좋은 출발점을 제공했습니다. 개념적으로 "프로세서"이지만 실제 CPU의 복잡한 세부 사항에서 매우 추상화되었습니다. 또한 학습 과정에서 중요하고 종종 간과되는 부분을 제공합니다. 예전에는 라디오 세트를 사용했던 아이들처럼 다시 조립하기 전에 물건을 분해합니다.

디 컴파일러와 Java의 Hello, World 클래스를 사용해보십시오. JVM 스펙을 읽고 무슨 일이 일어나고 있는지 이해하려고 노력하십시오. 이것은 컴파일러가 하는 일에 대한 통찰력을 제공합니다 .

그런 다음 Hello, World 클래스 를 작성 하는 코드를 가지고 놀아보십시오 . 실제로 실제로 Hello, World 만 말할 수있는 고도로 전문화 된 언어를위한 응용 프로그램 별 컴파일러를 만들고 있습니다.

다른 언어로 작성된 Hello, World로 읽을 수있는 코드를 작성하고 동일한 클래스를 출력하십시오. 문자열을 "Hello, World"에서 다른 것으로 변경할 수 있도록 만드십시오.

이제 "2 * (3 + 4)"와 같은 산술 표현식을 계산하는 클래스를 Java로 컴파일하십시오. 이 클래스를 분리하여 다시 합칠 수있는 "장난감 컴파일러"를 작성하십시오.


3

1) University of Washington의 훌륭한 비디오 강의 :

CSE P 501 컴파일러 구성-2009 년 가을 www.cs.washington.edu/education/courses/csep501/09au/lectures/video.html *

2) SICP http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/ 그리고 같은 이름의 책. 이것은 실제로 모든 소프트웨어 엔지니어에게 필수적입니다.

3) 또한 함수형 프로그래밍을위한 Haskell, 람다 미적분학, 의미론 (의사 포함) 및 컴파일러 구현에 대한 함수 프로그래밍. Haskell을 이미 알고 있다면 2005-SS-FP.V10.2005-05-24.HDV부터 시작할 수 있습니다. Uxx 비디오는 답변입니다. Vxx 비디오를 먼저 따르십시오 .

http://video.s-inf.de/#FP.2005-SS-Giesl.(COt).HD_Videoaufzeichnung

(비디오는 영어로되어 있고 다른 코스는 독일어로되어 있습니다.)

  • 신규 사용자는 최대 2 개의 하이퍼 링크 만 게시 할 수 있습니다.

3

ANTLR 은 좋은 출발점입니다. Lex 및 Yacc와 유사한 언어 생성 프레임 워크입니다. 프로세스를 단순화하는 ANTLRWorks 라는 GUI 가 있습니다.

.NET 세계에는 .NET 세계 에서 코드를 생성하는 데 사용할 수있는 동적 언어 런타임 이 있습니다. DLR을 사용하여 코드를 생성하는 Zentrum 이라는 표현 언어를 작성했습니다 . 정적으로 동적으로 형식화 된 표현식을 구문 분석하고 실행하는 방법을 보여줍니다.


2

컴파일러의 작동 방식과 자신 만의 프로그래밍 언어를 만드는 방법에 대한 간단한 소개를 위해 OS / CPU 내부, 즉 어휘 분석기, 파서에 대해 알 필요없이 언어 설계 이론에 더 초점을 맞춘 새로운 책 http://createyourproglang.com 을 추천합니다. , 통역사 등

최근 인기있는 Coffee ScriptFancy 프로그래밍 언어 를 만드는 데 사용 된 것과 동일한 도구를 사용합니다 .


2

당신이 말하는 모든 것이 사실이라면, 유망한 연구원의 프로필을 가지고 있으며, 한 가지 방법, 즉 공부를 통해 구체적인 이해를 얻을 수 있습니다. 그리고 나는 " 이 천재가 쓴이 모든 수준의 컴퓨터 과학 서적 (특히 이것들 )을 읽어라! "라고 말하지 않습니다 . 내 말은 : Charles Babbage, Alan Turing, Claude Shannon 또는 Dennis Ritchie와 같은 컴퓨터 과학자가 되려면 높은 수준의 사람들과 함께 있어야합니다. 나는 자발적인 사람들을 멸시하지 않고 (나는 그들 중 하나입니다) 그러나 당신과 같은 사람들은 많지 않습니다. Stanford University의 Symbolic Systems Program (SSP) 을 진심으로 추천 합니다. 그들의 웹 사이트에 따르면 :

Stanford University의 Symbolic Systems Program (SSP)은 컴퓨터와 정신, 즉 기호를 사용하여 정보를 나타내는 인공 및 자연 시스템에 중점을 둡니다. SSP는 다음을 포함하여 인간-컴퓨터 관계의 다양한 측면에 관심이있는 학생과 교수를 한자리에 모았습니다.

  • 인지 과학 : 인간 지능, 자연 언어 및 뇌를 전산 과정으로 연구;
  • 인공 지능 : 컴퓨터에 인간과 같은 행동과 이해력을 부여;
  • 휴먼-컴퓨터 상호 작용 : 휴먼 사용자와 잘 작동하는 컴퓨터 소프트웨어 및 인터페이스 설계.

2

저는 왼편에서 약간 벗어난 것을 제안하려고합니다. 파이썬을 배우십시오. 그리고 그것에 손을 대는 것이 아니라 실제로 그것을 깊은 수준에서 알게됩니다.

내가 이것을 제안하는 몇 가지 이유가 있습니다.

  1. 파이썬은 매우 잘 설계된 언어입니다. 사마귀가 적지 만 다른 언어보다 IMHO가 적습니다. 신진 언어 디자이너라면 가능한 한 많은 좋은 언어를 접하는 것이 좋습니다.

  2. 파이썬의 표준 구현 (CPython)은 오픈 소스이며 잘 문서화되어있어 언어가 어떻게 작동하는지 쉽게 이해할 수 있습니다.

  3. 파이썬은 어셈블리보다 이해하기 쉽고 파이썬이 실행되는 모든 플랫폼에서 동일하게 작동하는 간단한 바이트 코드로 컴파일됩니다. 따라서 컴파일 (파이썬이 소스 코드를 바이트 코드로 컴파일하기 때문에)과 해석 (이 바이트 코드가 파이썬 가상 머신에서 해석되므로)에 대해 배우게됩니다.

  4. 파이썬에는 수많은 PEP (Python Enhancement Proposals)에 문서화 된 새로운 기능이 많이 있습니다. PEP는 언어 설계자가 실제로 수행 한 방식을 선택하기 전에 기능 구현을 고려한 방법을 알아 보는 데 흥미가 있습니다. (여전히 고려중인 PEP는이 점에서 특히 흥미 롭습니다.)

  5. 파이썬에는 다양한 프로그래밍 패러다임의 기능이 혼합되어 있으므로 문제 해결에 접근하는 다양한 방법에 대해 배우고 자신의 언어로 포함시키는 다양한 도구를 사용할 수 있습니다.

  6. 파이썬을 사용하면 데코레이터, 메타 클래스, 가져 오기 후크 등을 사용하여 다양한 방식으로 언어를 쉽게 확장 할 수 있으므로 실제로 언어를 벗어나지 않고도 새로운 언어 기능을 사용할 수 있습니다. (제외 적으로 : 코드 블록은 Ruby의 최고급 객체이므로 실제로 루프와 같은 새로운 제어 구조를 작성할 수 있습니다! Ruby 프로그래머가 언어를 확장한다고 반드시 생각하지는 않는다는 인상을 얻습니다. 루비로 프로그램 하긴하지만 정말 멋집니다.)

  7. 파이썬에서는 실제로 컴파일러가 생성 한 바이트 코드를 디스 어셈블하거나 직접 작성하여 인터프리터가 실행하도록 할 수 있습니다 (이 작업은 직접 수행했지만 마음이 많이 들었지만 재미있었습니다).

  8. 파이썬에는 구문 분석을위한 좋은 라이브러리가 있습니다. Python 코드를 추상 구문 트리로 구문 분석 한 다음 AST 모듈을 사용하여 조작 할 수 있습니다. PyParsing 모듈은 디자인 한 언어와 같은 임의의 언어를 구문 분석하는 데 유용합니다. 원하는 경우 이론적으로 파이썬으로 첫 번째 언어 컴파일러를 작성할 수 있습니다 (그리고 C, 어셈블리 또는 Python 출력을 생성 할 수도 있음).

이 조사 방식은 작업중인 언어로 공부 한 개념을 인식하기 시작하고 그 반대의 경우에도보다 공식적인 접근 방식과 잘 어울립니다.

즐기세요!


파이썬을 파지 말고 요점은 아닙니다. 아이는 이미 큰 N에 대해 N 개의 언어를 가지고 있습니다. N을 증가 시키면 큰 차이가 없습니다. 예를 들어 C를 사용하십시오. 표준입니다. 많은 라이브러리가 있습니다. 크로스 플랫폼입니다 (표준을 고수 할 때). 출력을 분해 할 수 있습니다. CFront를 작성할 수 있습니다. 등등.
Ian

1

글쎄, 나는 당신의 질문이 "컴퓨터 과학 학위의 핵심 실제 개념은 무엇입니까?"라고 다시 쓰여질 수 있다고 생각합니다. 그리고 총체적인 대답은 물론 컴퓨터 과학 학사 학위를받는 것입니다.

기본적으로 텍스트 파일을 읽고, 정보를 추출하고, 읽은 정보를 기반으로 텍스트를 읽을 수있는 바이트로 변환 할 때까지 텍스트에서 변환을 수행하여 고유 한 프로그래밍 언어 컴파일러를 작성합니다. 로더 (참조 : Levine의 링커 및 로더). 사소한 컴파일러는 처음 수행했을 때 상당히 엄격한 프로젝트입니다.

운영 체제의 핵심은 리소스 (예 : 메모리 할당 / 할당 해제)를 관리하고 작업 / 프로세스 / 프로그램 간을 전환하는 커널입니다.

어셈블러는 텍스트-> 바이트 변환입니다.

이 내용에 관심이 있다면 Linux에서 표준 X86 어셈블리의 일부를 지원하는 X86 어셈블러를 작성하는 것이 좋습니다. 이는 매우 간단한 진입 점이며 이러한 문제를 소개합니다. 그것은 아기 프로젝트가 아니며 많은 것을 가르쳐 줄 것입니다.

나는 C로 작성하는 것이 좋습니다; C는 해당 수준의 작업에 대한 언어입니다.


1
반면에, 이것은 매우 높은 수준의 언어를위한 훌륭한 장소입니다. 파일에서 개별 바이트를 지시 할 수있는 한, 어떤 언어로든 컴파일러 / 어셈블러 (더 쉬운)를 만들 수 있습니다. 펄. 또는 VBA. 천국, 가능성!
Ian

1

Kenneth Louden의 저서 "컴파일러 구성"참조

http://www.cs.sjsu.edu/~louden/cmptext/

컴파일러 개발에 더 나은 실습 접근 방식을 제공합니다.

사람들은 행동함으로써 배웁니다. 적은 수의 사람 만이 칠판에 흩어져있는 기호를 볼 수 있으며 이론에서 바로 뛰어 넘을 수 있습니다. 불행하게도, 그 사람들은 종종 독단적이고 근본 주의적이며 가장 큰 사람들입니다.


1

나는 첫 번째 언어로 PDP-8에 노출되는 축복을 받았습니다. PDP-8은 단지 6 개의 명령 만 가지고 있었으며, 매우 간단해서 몇 개의 신중한 구성 요소로 구현되었다고 상상하기가 쉬웠습니다. 그것은 실제로 컴퓨터에서 "매직"을 제거했습니다.

같은 계시에 대한 또 다른 관문은 Knuth가 그의 예제에서 사용하는 "혼합"어셈블리 언어입니다. "믹스 (Mix)"는 오늘날에는 구식으로 보이지만 여전히 미 신화 효과가 있습니다.


0

컴파일러 및 프로그래밍 언어 (및 유한 문법 정의 및 어셈블리 변환과 같은 하나를 빌드하는 것을 포함하여 모든 것)는 시스템 전체에 대해 많은 이해가 필요한 매우 복잡한 작업입니다. 이 과정은 일반적으로 대학에서 3/4 학년 Comp Sci 수업으로 제공됩니다.

먼저 운영 체제에 대한 일반적인 이해와 기존 언어가 컴파일 / 실행되는 방법 (예 : 기본적으로 (C / C ++), VM (Java) 또는 인터프리터 (Python / Javascript))에 대해 더 잘 이해하는 것이 좋습니다.

필자는 운영 체제 과정에서 2 차 년도에 Abraham Silberschatz, Peter B. Galvin, Greg Gagne의 운영 체제 개념 책을 사용했다고 생각합니다. 이 책은 운영 체제의 각 구성 요소에 대한 철저한 설명을 제공하는 훌륭한 책으로 약간 비싸지 만 가치가 있으며 오래되었거나 사용 된 사본이 떠 있어야합니다.


OS 개념? 컴파일러를 빌드하는 데 필요한 것은 거의 없습니다. 공간, 스택, 스레드를 처리하는 소프트웨어 아키텍처에 대한 이해가 필요합니다 (컴파일러를 배우려면 병렬 처리와 미래에 대해 더 잘 배우십시오).
Ira Baxter

그는 언어 디자인과 컴파일러를 배우고 싶다고 말한 직후 OS에 대해 배우고 싶다고 말했다.
David Thornley

@Ira-동의했습니다. 필자는 컴파일러 / 언어를 빌드하기 위해 OS를 이해해야한다고 언급하지 않았으며, 더 쉬운 시작점이 될 수 있다고 간단히 설명했다. 모든 사람은 그의 질문의 '컴파일러'측면에 초점을 맞추고 있지만 OS와 라이브러리에 대해 더 잘 이해하고 싶다고 언급했습니다. 아키텍처에 대해 여전히 15 년이 된 학습의 경우 yacc (IMHO)를 사용하여 문법을 정의하는 방법을 배우는 것보다 메모리 관리, 스레딩, 잠금, I / O 등을 이해하는 것이 훨씬 유용합니다.
plafond

죄송합니다 ... OS 구축에 대해 배우고 자하는 요점을 놓쳤습니다. 내 요점은 : 그는 컴파일러에 대한 많은 OS 지식이 필요하지 않습니다. 실제로 컴파일러와 OS가 상호 작용하여 집단적 목적을 달성하는 것을 제외하고는 완전히 다른 주제입니다. (예를 들어 Multics는 글로벌 VM을 활성화하기 위해 특정 방식으로 함수 호출을 빌드하기 위해 PL / 1 컴파일러가 필요했습니다).
Ira Baxter

0

그것은 큰 주제이지만, "책을 읽고, 아이를 읽어라"라는 말로 당신을 털어 놓는 대신 머리를 감싸는 데 도움이되는 포인터를 기꺼이 줄 것이다.

대부분의 컴파일러 및 / 또는 인터프리터는 다음과 같이 작동합니다.

토큰 화 : 코드 텍스트를 스캔하여 토큰 목록으로 나눕니다.

공백으로 문자열을 분리 할 수 ​​없기 때문에이 단계는 까다로울 수 있습니다 if (bar) foo += "a string";. WORD, OPEN_PAREN, WORD, CLOSE_PAREN, WORD, ASIGNMENT_ADD, STRING_LITERAL, TERMINATOR 등 8 개의 토큰 목록 임을 인식해야 합니다. 보시다시피 공백으로 소스 코드를 나누는 것만으로는 작동하지 않으므로 각 문자를 시퀀스로 읽어야하므로 영숫자 문자가 발생하면 영숫자가 아닌 문자를 입력 할 때까지 문자를 계속 읽습니다. 읽기만하면 나중에 더 분류 할 단어입니다. 토크 나이저가 지 여부와 상관없이 토큰 가 얼마나 세밀한 지 스스로 결정할 수 있습니다."a string" 나중에 STRING_LITERAL이라는 하나의 토큰으로 거나 나중에 더 구문 분석할지 여부를 결정할 수 있습니다."a string" OPEN_QUOTE, UNPARSED_TEXT, CLOSE_QUOTE 등 무엇이든 코딩 할 때 스스로 결정해야하는 많은 선택 중 하나입니다.

Lex : 이제 토큰 목록이 생겼습니다. 첫 번째 패스 동안 각 문자열의 컨텍스트를 파악하는 데 너무 많은 노력을 기울이지 않기 때문에 WORD와 같이 모호한 분류로 일부 토큰에 태그를 지정했을 수 있습니다. 이제 소스 토큰 목록을 다시 읽고 모호한 토큰을 언어별로 키워드를 기반으로보다 구체적인 토큰 유형으로 다시 분류하십시오. 따라서 "if"와 같은 WORD가 있고 "if"가 symbol IF라는 특수 키워드 목록에 있으므로 해당 토큰의 기호 유형을 WORD에서 IF로 변경하고 특수 키워드 목록에없는 WORD를 변경하십시오. foo와 같은은 IDENTIFIER입니다.

구문 분석 : 이제 if (bar) foo += "a string";다음과 같은 어휘 토큰 목록을 설정했습니다. IF OPEN_PAREN IDENTIFER CLOSE_PAREN IDENTIFIER ASIGN_ADD STRING_LITERAL TERMINATOR. 이 단계는 토큰 시퀀스를 명령문으로 인식합니다. 이것은 파싱입니다. 다음과 같은 문법을 사용하면됩니다 :

진술 : = ASIGN_EXPRESSION | IF_STATEMENT

IF_STATEMENT : = IF, PAREN_EXPRESSION, 진술

ASIGN_EXPRESSION : = IDENTIFIER, ASIGN_OP, VALUE

PAREN_EXPRESSSION : = OPEN_PAREN, VALUE, CLOSE_PAREN

VALUE : = 아이디 | STRING_LITERAL | PAREN_EXPRESSION

ASIGN_OP : = EQUAL | ASIGN_ADD | ASIGN_SUBTRACT | ASIGN_MULT

"|"를 사용하는 프로덕션 용어 사이의 용어는 "이들 중 하나와 일치"를 의미하며, 용어 사이에 쉼표가 있으면 "이 순서의 용어와 일치"를 의미합니다.

이것을 어떻게 사용합니까? 첫 번째 토큰부터 시작하여 일련의 토큰을 이러한 프로덕션과 일치 시키십시오. 먼저 토큰 목록을 STATEMENT와 일치 시키려고하면 STATEMENT의 규칙을 읽고 "STATEMENT는 ASIGN_EXPRESSION 또는 IF_STATEMENT"이므로 ASIGN_EXPRESSION과 먼저 일치 시키려고하므로 ASIGN_EXPRESSION에 대한 문법 규칙을 찾습니다. "ASIGN_EXPRESSION은 IDENTIFIER 다음에 ASIGN_OP 뒤에 VALUE가 있습니다. 따라서 IDENTIFIER에 대한 문법 규칙을 검색하고 IDENTIFIER에 대한 문법 규칙이 없으므로 IDENTIFIER가"터미널 "임을 의미하므로 더 이상 필요하지 않습니다. 토큰과 직접 일치 시키려고 구문 분석하지만 첫 번째 소스 토큰은 IF이고 IF는 IDENTIFIER와 동일하지 않으므로 일치하지 못했습니다. 지금 무엇? STATEMENT 규칙으로 돌아가 다음 용어 IF_STATEMENT와 일치 시키십시오. IF_STATEMENT 조회, IF로 시작, IF 조회, IF는 터미널, 첫 번째 토큰과 터미널 비교, 토큰 일치, 멋진 토큰 계속, 다음 기간은 PAREN_EXPRESSION, 조회 PAREN_EXPRESSION, 터미널이 아닙니다. 첫 번째 용어는 무엇입니까? PAREN_EXPRESSION은 OPEN_PAREN (으)로 시작하고 OPEN_PAREN (검색) OPEN_PAREN (단말기)입니다. OPEN_PAREN (을)를 다음 토큰에 일치 시키면 일치합니다.

이 단계에 접근하는 가장 쉬운 방법은 parse ()라는 함수를 사용하여 일치시키려는 소스 코드 토큰과 일치시키려는 문법 용어를 전달하는 것입니다. 문법 용어가 터미널이 아닌 경우 되풀이됩니다. parse ()를 다시 호출하여 동일한 문법 토큰과이 문법 규칙의 첫 번째 용어를 전달합니다. 이것이 "재귀 하강 파서 (recursive descent parser)"라고 불리는 이유이다. parse () 함수는 소스 토큰을 읽을 때 현재 위치를 반환 (또는 수정)하며, 일치하는 순서로 마지막 토큰을 다시 전달하며 다음 호출을 계속한다 거기에서 구문 분석하십시오.

parse ()가 ASIGN_EXPRESSION과 같은 프로덕션과 일치 할 때마다 해당 코드 조각을 나타내는 구조를 만듭니다. 이 구조에는 원본 소스 토큰에 대한 참조가 포함됩니다. 이러한 구조의 목록을 작성하기 시작합니다. 이 전체 구조를 AST (Abstract Syntax Tree)라고합니다.

컴파일 및 / 또는 실행 : 문법의 특정 프로덕션에 대해 AST 구조가 제공되면 해당 AST 청크를 컴파일하거나 실행하는 핸들러 함수를 작성했습니다.

ASIGN_ADD 유형의 AST 부분을 살펴 보겠습니다. 따라서 인터프리터로서 ASIGN_ADD_execute () 함수가 있습니다. 이 함수는에 대한 구문 분석 트리에 해당하는 AST의 일부로 전달되므로이 foo += "a string"함수는 해당 구조를보고 구조의 첫 번째 용어는 IDENTIFIER이고 두 번째 용어는 VALUE이어야한다는 것을 알고 있으므로 ASIGN_ADD_execute () 메모리에 평가 된 값을 나타내는 객체를 반환하는 VALUE_eval () 함수에 VALUE 용어를 전달한 다음 ASIGN_ADD_execute ()는 변수 테이블에서 "foo"를 조회하고 eval_value ()에 의해 반환 된 모든 것에 대한 참조를 저장합니다. 기능.

통역사입니다. 컴파일러는 대신 핸들러 함수가 AST를 실행하는 대신 AST를 바이트 코드 또는 기계 코드로 변환하도록합니다.

Flex 및 Bison과 같은 도구를 사용하여 1 단계에서 3 단계, 그리고 4 단계를 더 쉽게 수행 할 수 있습니다. (일명 Lex와 Yacc) 통역사를 처음부터 작성하는 것은 아마도 프로그래머가 달성 할 수있는 가장 강력한 운동 일 것입니다. 다른 모든 프로그래밍 문제는 이것을 정상화 한 후에 사소한 것처럼 보입니다.

저의 조언은 작은 문법으로 작은 언어로 시작하고, 몇 가지 간단한 문장을 파싱하고 실행 해 본 다음 거기서 자라나는 것입니다.

이것들을 읽고 행운을 빕니다!

http://www.iro.umontreal.ca/~felipe/IFT2030-Automne2002/Complements/tinyc.c

http://en.wikipedia.org/wiki/Recursive_descent_parser


2
사람들이 컴파일에 대해 생각할 때 고전적인 실수라고 생각하는 것을 만드십시오. 문제가 파싱에 있다고 믿는 것입니다. 패싱은 기술적으로 쉽습니다. 이를위한 훌륭한 기술이 있습니다. 컴파일에있어 어려운 부분은 요즘 PARALLEL 코드에 대한 강조가 높아짐에 따라 의미 론적 분석, 높고 낮은 수준의 프로그램 표현 및 코드 생성에 최적화됩니다. "컴파일러에는 AST를 바이트 코드로 변환하는 핸들러 함수가 있습니다." 거기에는 50 년의 컴파일러 이론과 엔지니어링이 숨겨져 있습니다.
Ira Baxter

0

컴퓨터 분야는 여러 방향으로 진화 할 시간이 있었기 때문에 복잡합니다. 그 핵심은 계산하는 기계에 관한 것입니다.

내가 가장 좋아하는 컴퓨터는 Harry Porter 's Relay Computer 입니다. 컴퓨터가 기본 수준에서 작동하는 방식을 맛볼 수 있습니다. 그런 다음 언어 및 운영 체제와 같은 것들이 필요한 이유를 이해할 수 있습니다.

중요한 것은 필요한 것이 무엇인지 이해하지 않고는 이해하기 어렵다는 입니다. 행운을 빌어 요, 그냥하지 않는 읽기 물건을. 수행 물건을.



-1

또 다른 좋은 입문 서적은 1986 년 N. Wirth의 "컴파일러 바우 (Compilerbau)"(약 100 페이지)이며 파서, 코드 생성기 및 가상 머신을 포함하여 장난감 언어 PL / 0에 대해 간결하고 잘 설계된 코드를 설명합니다. 또한 EBNF 표기법으로 구문 분석하기 위해 문법을 읽는 구문 분석기를 작성하는 방법도 보여줍니다. 이 책은 독일어이지만 요약본을 작성하고 코드를 연습으로 파이썬으로 번역했습니다 . http://www.d12k.org/cmplr/w86/intro.html을 참조 하십시오 .


-1

프로그래밍 언어의 본질을 이해하는 데 관심이 있다면 PLAI (http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/) 책을 통해 개념을 이해하고 제안하는 것이 좋습니다. 그들의 구현. 또한 자신의 언어 디자인에 도움이됩니다.


-1

컴파일러에 관심이 있고 전에 한 번도 해본 적이 없다면 산술 공식 계산을위한 계산기를 설계하는 것으로 시작할 수 있습니다 (Eric이 언급 한 DSL 종류). 이러한 종류의 컴파일러에 대해 고려해야 할 많은 측면이 있습니다.

  • 허용되는 숫자
  • 허용 된 운영자
  • 운영자 우선 순위
  • 구문 검증
  • 변수 조회 메커니즘
  • 사이클 감지
  • 최적화

예를 들어 다음과 같은 수식이 있으면 계산기에서 x 값을 계산할 수 있어야합니다.

a = 1
b = 2
c = a + b
d = (3 + b) * c
x = a - d / b

시작하기가 매우 어려운 컴파일러는 아니지만 컴파일러가 무엇인지에 대한 기본 아이디어를 더 많이 생각할 수 있으며 프로그래밍 기술을 향상시키고 코드의 품질을 제어하는 ​​데 도움이 될 수 있습니다 (실제로는 완벽한 문제입니다) 테스트 중심 개발 TDD는 소프트웨어 품질 향상을 위해 적용될 수 있습니다).

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