크 툴후 길을 파싱하는 것에 대한 논쟁은 무엇인가?


24

회사에 중요한 도구가 될 도메인 특정 언어를 구현하는 임무를 맡았습니다. 이 언어는 단순하지만 사소한 것이 아니라 이미 중첩 루프, 문자열 연결 등을 허용하며 프로젝트가 진행됨에 따라 다른 구문이 추가 될 것입니다.

나는 문법이 사소한 것이 아닌 한, 직접 렉서 / 파서를 작성하는 것은 시간이 걸리고 오류가 발생하기 쉬운 프로세스라는 것을 알고있다. 그래서 나는 파서 생성기 à la yacc 또는 Parsec과 같은 결합기 라이브러리의 두 가지 옵션이 남았습니다. 전자도 좋지만 여러 가지 이유로 후자를 선택하고 기능적 언어로 솔루션을 구현했습니다.

결과는 내 눈에 매우 훌륭하고 코드는 매우 간결하고 우아하며 읽기 쉽고 유창합니다. java / c # 이외의 다른 프로그램을 프로그래밍하지 않으면 조금 이상하게 보일 수 있지만 java / c #으로 작성되지 않은 것은 사실입니다.

그러나 어느 시점에서 나는 문자 그대로 동료의 공격을 받았습니다. 내 화면을 간략히 살펴본 후 코드를 이해할 수 없으며 구문 분석을 다시하지 말고 스택과 String을 사용하면된다고 선언했습니다. 그는 많은 소음을 냈으며, 나는 놀랍게도 설명이 없었기 때문에 부분적으로 설득 할 수 없었다. 나는 심지어 그에게 언어를 설명하라고 제안했지만 아무 소용이 없었다.

토론이 경영진 앞에서 다시 등장 할 것이므로 긍정적 인 주장을하고 있습니다.

이것이 String.Split 기반 솔루션을 피하기 위해 떠오른 처음 몇 가지 이유입니다.

  • 특별한 경우를 처리하기 위해 많은 if가 필요하며 물건을 빨리 통제 할 수 없게 만듭니다.
  • 하드 코딩 된 배열 인덱스가 많으므로 유지 관리가 어려움
  • 함수 호출과 같은 것을 메서드 인수로 처리하기가 매우 어렵습니다 (예 : add ((add a, b), c)
  • 구문 오류가 발생할 경우 의미있는 오류 메시지를 제공하기가 매우 어렵습니다 (매우 발생할 수 있음)
  • 나는 단순성, 명확성 및 불필요한 스마트 암호를 피하기 위해 모두 노력하고 있지만, 햄버거 플리퍼조차도 그것을 이해할 수 있도록 코드베이스의 모든 부분을 멍청하게 만드는 것은 실수라고 생각합니다. 인터페이스를 사용하지 않고, 문제를 구분하지 않고, 코드를 복사하여 붙여 넣는 등의 말을 듣는 것과 같은 주장입니다. 결국 소프트웨어 프로젝트를 수행하려면 최소한의 기술적 역량과 배우려는 의지가 필요합니다. (이 주장은 아마도 불쾌하게 들릴 것이므로 사용하지 않을 것이며, 전쟁을 시작해도 아무도 도움이되지 않을 것입니다)

크 툴후 길을 파싱 하는 것에 대해 당신이 가장 좋아하는 주장은 무엇입니까 ? *

* 물론 그가 옳다는 것을 확신 할 수 있다면 나는 또한 완전히 행복 할 것이다.


9
동료가 DSL 프로젝트를 위해 자원 봉사하는 것처럼 들립니다.
GrandmasterB

23
"나는 구문 분석 재발견하지만 단지 스택 사항 String.split 모든 사람들이하는 것처럼 사용하지 말아야"- 젠장, 그 사람은 무지가 다치게하지 않는다는 것을 기뻐한다 ...
마이클 Borgwardt

4
동료가 드래곤 북 전체를 읽고 시험에 합격하지 않는 한이 토론으로 돌아 가지 말라고 조언하십시오. 그렇지 않으면 파싱 관련 내용을 논의 할 권리가 없습니다.
SK-logic

4
죄송합니다. 누가 파싱을 재발 명했습니까?
rwong

2
다음에 "문자 적으로"단어를 비 유적으로 사용하는 사람을 보면 머리가 말 그대로 터질 것입니다.

답변:


33

두 가지 접근 방식의 중요한 차이점은 그가 올바른 방법이라고 생각하는 것이 필수적이며 귀하의 접근 방식은 선언적이라는 것입니다.

  • 접근 방식은 규칙을 명시 적으로 선언합니다. 즉, 문법 규칙이 코드에서 (거의) 직접 인코딩되며 파서 라이브러리는 자동으로 원시 입력을 구문 분석 된 출력으로 변환하면서 상태 및 처리하기 어려운 사항을 처리합니다. 코드는 하나의 단일 추상화 계층 내에 작성되며 문제 도메인과 일치합니다 : 구문 분석. parsec의 정확성을 가정하는 것이 합리적입니다. 여기서 오류의 유일한 여지가 문법 정의가 잘못되었음을 의미합니다. 그러나 다시 한 번 정규화 된 규칙 객체가 있으며 쉽게 격리 테스트됩니다. 또한 성숙한 파서 라이브러리에는 하나의 중요한 기능인 오류보고 기능이 포함되어 있습니다. 구문 분석이 잘못되었을 때 적절한 오류 복구는 쉽지 않습니다. 증거로 PHP의 parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM: D를 호출합니다 .

  • 그의 접근 방식은 문자열을 조작하고 명시 적으로 상태를 유지하며 원시 입력을 수동으로 구문 분석 된 입력으로 들어 올립니다. 오류보고를 포함하여 모든 것을 직접 작성해야합니다. 그리고 무언가 잘못되면 완전히 사라집니다.

아이러니는 접근 방식으로 작성된 파서의 정확성이 비교적 쉽게 입증된다는 것입니다. 그의 경우 거의 불가능합니다.

소프트웨어 설계를 구성하는 두 가지 방법이 있습니다. 한 가지 방법은 간단하게 결함이 없도록하고, 다른 방법은 너무 복잡하게하여 명백한 결함이없는 것입니다. 첫 번째 방법은 훨씬 더 어렵다.

차 Hoare

당신의 접근 방식 더 간단합니다. 그것이 배제하는 것은 그가 수평선을 조금 넓히는 것입니다. 그의 접근 방식의 결과는 당신의 시야가 아무리 넓어도 항상 복잡합니다.
솔직히 말해서, 그 남자는 무지한 바보이며, Blub 증후군으로 고통 받고 있습니다.

그러나 결국 문제는 누가 그것을 유지해야 하는가하는 것입니다. 그것이 당신이라면 누구의 말이든 상관없이 당신의 전화입니다. 그것이 그가 될 것이라면, 두 가지 가능성이 있습니다 : 파서 ​​라이브러리를 이해하게하거나 그를 위해 명령 파서를 작성하는 방법을 찾으십시오. 파서 구조에서 생성하는 것이 좋습니다. : D


두 접근법의 차이점에 대한 훌륭한 설명.
smarmy53

6
프로그래머 용 TVTropes에 연결된 것 같습니다. 안녕 오후 ...
Izkata

10

Packrat 구문 분석기 접근 방식과 같은 구문 분석 표현식 문법 또는 구문 분석기 결합기가 구문 분석을 재발 명하지 않습니다. 이들은 함수형 프로그래밍 세계에서 잘 확립 된 기술이며, 오른쪽에서 대안보다 더 읽기 쉽습니다. 몇 년 전에 C #에서 PEG에 대해 상당히 설득력있는 데모를 보았는데, 실제로 비교적 간단한 문법을위한 첫 번째 수단이되었습니다.

파서 콤비 네이터 나 PEG를 사용하는 우아한 솔루션이 있다면 상대적으로 쉽게 팔 수 있습니다. 함수형 프로그래밍에 대한 두려움을 극복 한 후에는 일반적으로 비교적 쉽게 읽을 수 있으며, 일반적인 파서 생성기보다 읽기가 쉽습니다. 도구는 문법과 도구 세트에 대한 경험 수준에 따라 크게 달라집니다. 테스트를 작성하는 것도 매우 쉽습니다. 물론 최악의 시나리오 (또는 Packrat를 사용한 많은 메모리 소비)에서 구문 분석 성능이 끔찍한 문법 모호성이 있지만, 평균 케이스는 꽤 괜찮으며 실제로 일부 문법 모호성은 LALR보다 PEG로 더 잘 처리됩니다. 기억합니다

Split 및 스택을 사용하면 PEG보다 간단한 문법으로 작동하거나 지원할 수 있지만 시간이 지남에 따라 재귀 강하를 잘못 재발하거나, 또는 악의적 인 행동이 발생할 가능성이 큽니다. 구조화되지 않은 코드를 사용하여 제출하는 데 도움이됩니다. 간단한 토큰 화 규칙 만 있다면 그렇게 나쁘지는 않지만 복잡성을 추가하면 유지 관리가 가장 적은 솔루션 일 것입니다. 대신 파서 생성기에 도달했습니다.

개인적으로 DSL을 구축해야 할 때의 첫 번째 성향은 매크로 및 간단한 조정을 작성하여 기존 프로그래밍 언어의 강점과 놀라운 사용자 정의 기능을 모두 얻기 때문에 Boo (.Net) 또는 Groovy (JVM)와 같은 것을 사용하는 것입니다. 컴파일러 파이프 라인에, 제로 (루프, 변수, 객체 모델 등)에서 시작하면 지루한 작업을 수행하지 않아도됩니다. 루비 나 리스프 개발을하고있는 가게에 있다면, 그저 의미가있는 관용구 (메타 프로그래밍 등)를 사용합니다.

그러나 나는 당신의 진짜 문제가 문화 나 자아에 관한 것이라고 생각합니다. Antlr 또는 Flex / Bison을 사용한 경우 동료가 똑같이 놀라지 않았습니까? 귀하의 솔루션에 대한 "논쟁"이 패배 할 것으로 의심됩니다. 지역 관리 당국에 호소하지 않고 합의 구축 기술을 사용하는보다 부드러운 접근 방식을 수행하는 데 더 많은 시간을 소비해야 할 수도 있습니다. 페어 프로그래밍 및 유지 관리 성을 희생하지 않고 문법 조정을 얼마나 빨리 수행 할 수 있는지 시연하고 기술, 히스토리 등을 설명하기 위해 브라운 백을 수행하면 10 개 이상의 글 머리 기호 및 "무례한 Q & A"가 발생할 수 있습니다. 대결 회의.


9

나는 알고리즘 분석에 익숙하지 않지만 푸딩의 증거는 먹는 것에 있다고 생각합니다. 따라서 다른 모든 방법이 실패하면 파서를 구현하는 방법을 제안 할 수 있습니다. 그때

  • 두 솔루션에 투자 한 시간을 비교하고
  • 버그가 적은지 확인하기 위해 포괄적 인 승인 테스트를 통해 두 솔루션을 모두 실행
  • 독립적 인 판사에게 결과 코드의 크기와 선명도를 귀하의 코드와 비교하도록하십시오.

테스트가 실제로 공정하기 위해서는 두 솔루션 모두 동일한 API를 구현하고 공통 테스트 베드 (또는 둘 다 알려진 단위 테스트 프레임 워크)를 사용하려고 할 수 있습니다. 두 사람 모두 다양한 종류의 기능 테스트 사례를 작성하고 자신의 솔루션이 모든 사례를 통과하는지 확인할 수 있습니다. 물론 마감 시간 이전에 다른 사람의 구현에 액세스 할 수있는 것이 이상적입니다. 결정적인 테스트는 다른 개발자가 개발 한 테스트 스위트를 사용하여 두 솔루션을 교차 테스트하는 것 입니다.


이것은 좋은 생각입니다! 공통 단위 테스트 프레임 워크도 사용하기 쉽습니다.
smarmy53

1
동료가 분할 버전을 수행하도록 +1했습니다. OP는이를 생성하는 작업이므로 OP는 동료가 아니라 지원해야 할 가능성이 가장 높습니다. 그의 다른 작품 위에 그에게 제안하는 것만으로도 그를 등에서 내릴 수 있습니다.
Izkata

7

기술적 인 질문이있는 것처럼이 질문을했지만 이미 알고 있듯이 여기에는 기술적 인 질문이 없습니다. 당신의 접근 방식은 캐릭터 레벨에서 무언가를 해킹하는 것보다 훨씬 우수합니다.

진짜 문제는 당신의 (아마도 경험이 많은) 동료가 안전하지 않으며, 당신의 지식에 위협을 받는다는 것입니다. 당신은 그를 기술적 주장으로 설득하지 않을 것입니다 . 그를 더 방어 적으로 만들 것입니다. 대신에 당신은 그의 두려움을 완화시킬 방법을 찾아야 할 것입니다. 많은 제안을 할 수는 없지만 레거시 코드에 대한 지식을 높이 평가할 수 있습니다.

마지막으로, 관리자가 그의 기술적 주장에 동의하고 솔루션을 폐기하면 다른 입장을 찾아야한다고 생각합니다. 보다 정교한 조직에서는 더 가치 있고 가치가 높아질 것입니다.


당신은 옳았습니다. 저는 이미 제 접근 방식이 우수하다는 것을 알고 있었지만, 제가 찾고있는 기술 정보 인, 좋은 설득력있는 설명을 얻지 못했습니다. 문제의 "인간 상호 작용"측면은 기술적 인 측면만큼 중요합니다 (더 이상은 아님).
smarmy53

4

나는 간단 할 것이다 :

크 툴후 길을 파싱하는 것은 어렵다. 그것은 가장 단순하고 설득력있는 주장입니다.

간단한 언어에 대한 트릭을 수행 할 수 있습니다. 말하면, 정규 언어입니다. 그래도 정규 표현식보다 쉽지 않을 것입니다.

좀 더 복잡한 언어에 대한 트릭을 수행 할 수도 있습니다.

그러나 중첩 또는 "상당히 상태가 좋은"-수학적 표현 또는 예제 (중첩 함수 호출)가있는 모든 언어에 대한 Cthulhu 파서를보고 싶습니다.

누군가가 (사소한 맥락이없는) 언어에 대한 파서를 파문하려고하면 어떻게 될지 상상해보십시오 . 그가 올바른 파서를 작성하기에 충분히 영리하다면, 코딩하는 동안 그는 첫 번째 토큰을 발견 한 다음 재귀 강하 구문 분석을 어떤 형태로하겠다고 확신했다.

그 후에는 간단합니다. "이봐 요, 재귀 강하 파서 (recursive descent parser)라고하는 것을 작성했습니다! 정규 표현식처럼 간단한 문법 설명에서 자동으로 생성 될 수 있다는 것을 알고 있습니까?


짧은 이야기 :
누군가가 문명화 된 접근 방식을 사용하지 못하게 할 수있는 유일한 것은 그들의 무지입니다.


1

아마도 좋은 DSL 시맨틱을 다루는 것도 중요하다 (구문이 중요하지만 또한 시맨틱). 이 문제에 익숙하지 않다면 Programming Languages ​​Pragmatics (M.Scott)와 Christian Queinnec과 같은 책을 읽는 것이 좋습니다 . 작은 조각에 Lisp . 케임브리지 대학 출판부, 1996.

, 예를 들어 DSL 회의에서 최근의 논문을 읽고 DSL2011은 또한 도움을해야한다.

도메인 특정 언어를 디자인하고 구현하는 것은 어렵습니다 (대부분의 어려움은 파싱 되지 않습니다 !).

나는 Cthulhu 길파싱하여 당신이 무엇을 의미하는지 이해하지 못합니다 . 나는 당신이 어떻게 든 기괴한 방식으로 파싱하는 것을 의미한다고 생각합니다.


좋은 링크. 크 툴후는 미안하지만 링크를 잊어 버렸습니다. 그것은 고전 codinghorror 기사에 대한 참조입니다 : codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html . 원래 게시물을 업데이트했습니다.
smarmy53
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.