주석은 일반적으로 어떻게 파싱됩니까?


31

주석은 일반적으로 프로그래밍 언어 및 마크 업에서 어떻게 처리됩니까? 일부 사용자 정의 마크 업 언어에 대한 파서를 작성하고 있으며 가장 놀랄만원칙 을 따르고 싶습니다 . 따라서 일반적인 규칙을 결정하려고합니다.

예를 들어, 토큰에 포함 된 주석이 토큰과 '간섭'해야합니까? 일반적으로 다음과 같습니다.

Sys/* comment */tem.out.println()

유효한?

또한 언어가 줄 바꿈에 민감하고 주석이 줄 바꿈에 해당하는 경우 줄 바꿈을 고려해야합니까?

stuff stuff /* this is comment
this is still comment */more stuff 

~로 취급되다

stuff stuff more stuff

또는

stuff stuff
more stuff

?

몇 가지 특정 언어의 기능을 알고 있거나 의견을 찾고 있지는 않지만 찾고 있는지 여부는 찾고 있습니다. 토큰 및 줄 바꿈과 관련하여 마크 업에서 일반적으로 예상되는 일반적인 합의가 있습니까?


내 특정 상황은 위키와 같은 마크 업입니다.


줄 바꿈이 주석 안에 있습니까? 주석에서 다른 문자와 다르게 취급되는 이유는 무엇입니까?

1
@ Snowman은 그 관점이 있지만 반면에 토큰 'x'가 첫 번째 토큰이 라인의 첫 번째 토큰이고 소스를보고있는 사람과 파서는 한 줄씩 읽습니다. 딜레마 인 것 같아서 질문을했습니다.
Sled

4
나는 한참 전에이 작업을 정확하게 수행해야했고 gcc의 문서 가 훌륭한 리소스라는 것을 알았습니다 . 고려하지 않은 이상한 코너 사례가 있습니다.
Karl Bielefeldt

답변:


40

일반적으로 주석은 토큰 화 프로세스의 일부로, 구문 분석 전에 스캔 (및 삭제)됩니다. 주석은 주위에 공백이없는 경우에도 토큰 구분 기호처럼 작동합니다.

지적했듯이 C 사양에서는 주석이 단일 공백으로 대체된다고 명시 적으로 명시하고 있습니다. 그러나 실제 파서는 실제로 아무것도 대체하지 않지만 공백 문자를 스캔하고 버리는 것과 같은 방식으로 주석을 스캔하고 버릴 것이므로 사양에 불과합니다. 그러나 이것은 주석이 공백과 같은 방식으로 토큰을 분리하는 간단한 방법으로 설명합니다.

주석 내용은 무시되므로 여러 줄 주석 내의 줄 바꿈은 적용되지 않습니다. 줄 바꿈 (Python 및 Visual Basic)에 민감한 언어에는 일반적으로 여러 줄 주석이 없지만 JavaScript는 예외입니다. 예를 들면 다음과 같습니다.

return /*
       */ 17

에 해당

return 17

아니

return
17

한 줄 주석은 줄 바꿈을 유지합니다. 즉

return // single line comment
    17

에 해당

return
17

아니

return 17

주석은 스캔되지만 구문 분석되지 않으므로 중첩되지 않는 경향이 있습니다. 그래서

 /*  /* nested comment */ */

주석이 첫 번째에 의해 열리고 첫 번째에 /*의해 닫히기 때문에 구문 오류입니다.*/


3
대부분의 언어에서 인라인 주석 ( /* like this */)은 단일 공백과 같고 EOL 종료 주석 ( // like this)은 빈 줄과 같습니다.
9000

@JacquesB 그래서 의견을 소스에서 전체 너비0 인 공간 으로 대체 하는 것으로 생각하고 있습니다.
Sled

1
@artb 일반 공간은 정상적으로 작동하며 ASCII 코드 페이지에 있습니다.
John Dvorak

@JanDvorak 공간은 외관에 영향을 미치고 이해력을 제거하며 "주석이 실제로 존재하지 않습니다"라는 의미에 더 가깝습니다. 기본 렌더링 출력은 HTML이되므로 브라우저가 유니 코드를 지원하는 것처럼 ASCII가 문제가되지 않습니다. 즉, C 표준에서는 주석이 단일 공백으로 대체되어야한다고 주장합니다.
Sled

1
라켓과 같은 일부 언어에는 여러 줄 주석이 중첩되어 있습니다. (define x #| this is #| a sub-comment |# the main comment |# 3) xyields 3.
wchargin

9

질문에 대답하려면 :

마크 업으로 일반적으로 예상되는 일반적인 합의가 있습니까?

나는 토큰 안에 포함 된 주석이 합법적이라고 기대하지 않을 것이라고 말했다.

일반적으로 주석은 공백과 동일하게 취급해야합니다. 불필요한 공백이있을 수있는 모든 장소에도 주석이 포함되어야합니다. 유일한 예외는 문자열입니다.

trace("Hello /*world*/") // should print Hello /*world*/

문자열 내부의 주석을 지원하는 것은 매우 이상하며, 탈출하는 것은 지루합니다!


2
문자열에 대해 생각하지 마십시오. 좋은 경우입니다. 내 현재 생각은 주석 시작과 끝 사이에 간단한 정규 표현식을 수행하고 단일 공백으로 대체하는 것이 었습니다. 그것은 당신의 사건을 넘어 뜨렸을 것입니다.
Sled

3
이스케이프 문자열에 대한 비트에 +1. 귀하의 예에서는 일반적으로 Hello /* world*/!주석 구분 기호를 억제하지 않고 인쇄 할 것으로 기대합니다 . 또한 프로그래머에게 오신 것을 환영합니다!
8bittree

1
감사합니다 8bittree! 그리고 그것은 내가 의미 한 바입니다. 충분히 재미있게, 또한 .... 내 대답에 **을 탈출해야합니다
코너 클라크

2
@ArtB는 일반적으로 "대체 구문 분석"을 통해 최첨단 사례와 다른 기능과의 상호 작용을 통해 매우 까다로워지며 처음부터 피하는 것이 가장 좋습니다.
홉스

7

공백에 영향을받지 않는 언어에서 무시 된 문자 (예 : 공백 또는 주석의 일부)는 토큰을 구분합니다.

예를 들어 Sys tem두 개의 토큰이 있지만 System하나는 토큰 입니다. 이것의 유용성은 당신이 비교 new Foo()하고 newFoo()그중 하나가 Foo다른 호출을 하는 인스턴스를 구성 한다면 더 분명 할 것 newFoo입니다.

주석은 공백과 같은 역할을 할 수 있습니다 (예 : new/**/Foo()와 동일하게 작동) new Foo(). 물론 이것은 더 복잡 할 수있다 new /**/ /**/ Foo().

기술적으로 식별자 내에 주석을 허용하는 것이 가능해야하지만 특히 실용적이라고 생각합니다.

이제 공백에 민감한 언어는 무엇입니까?

파이썬은 생각 나고 매우 간단한 답변을 가지고 있습니다 : 블록 주석 없음. 주석을 시작 #하면 파서의 나머지 부분은 존재하지 않지만 대신 개행 문자처럼 작동합니다.

대조적으로, jade는 블록 주석을 허용합니다. 블록 은 동일한 들여 쓰기 수준으로 돌아갈 때 블록이 끝납니다. 예:

body
  //-
    As much text as you want
    can go here.
  p this is no longer part of the comment

따라서이 영역에서 일이 일반적으로 어떻게 처리 되는지 말할 수는 없습니다 . 공통적 인 것처럼 보이는 것은 주석이 항상 줄 끝으로 끝나는 것입니다. 즉, 모든 주석은 줄 바꿈과 동일하게 작동합니다.


흠, 개행은 주석에 HTML \ XML 구문을 사용하기 때문에 실제 문제입니다.
Sled

3
@ArtB HTML / XML 구문을 사용하는 경우 단순히 동작을 사용하는 것이 좋습니다.
8bittree

1
@ 8bittree는 의미가 있습니다. 이 방법이 더 유용 할 것이므로 질문을 그대로 두겠습니다.
썰매

3

과거에는 어휘 분석의 일환으로 주석을 단일 토큰으로 바꿨습니다. 문자열도 마찬가지입니다. 거기에서 인생은 쉽다.

내가 만든 마지막 파서의 특정 경우에는 이스케이프 규칙이 최상위 구문 분석 루틴으로 전달됩니다. 이스케이프 규칙은 주석 문법과 같은 토큰을 핵심 문법에 맞춰 처리하는 데 사용됩니다. 일반적으로 이러한 토큰은 폐기되었습니다.

이 방법으로 수행 한 결과 식별자 중간에 주석으로 게시 한 예제는 식별자가 단일 식별자가 아닙니다. 이것은 내가 작업 한 모든 언어 (메모리에서)에서 예상되는 동작입니다. .

문자열 내 주석의 경우는 어휘 분석에 의해 암시 적으로 처리되어야합니다. 문자열을 처리하는 규칙은 주석에 관심이 없으므로 주석은 문자열의 내용으로 취급됩니다. 주석 내의 문자열 (또는 인용 된 리터럴)에도 동일하게 적용됩니다. 문자열은 주석의 일부이며 명시 적으로 단일 토큰입니다. 주석 처리 규칙은 문자열에 관심이 없습니다.

이해가 되길 바랍니다.


따라서 console.log(/*a comment containing "quotes" is possible*/ "and a string containing /*slash-star, star-slash*/ is possible")문자열에 주석과 주석 구문에 따옴표가있는 곳 과 같은 코드 가있는 경우 어휘 분석기가 코드를 올바르게 토큰 화하는 방법을 어떻게 알 수 있습니까? 해당 사례에 대한 일반적인 설명을 제공하여 답변을 편집 할 수 있습니까?
chharvey

1

파서의 용도에 따라 다릅니다. 주석이 잠재적으로 토큰을 분리하는 것 외에 의미 론적 가치가없는 것보다 컴파일을 위해 구문 분석 트리를 작성하기 위해 파서를 작성하는 경우 (예 : 메소드 / comment / (/ comment /)). 이 경우 공간처럼 취급됩니다.

구문 분석기가 한 소스 언어를 다른 소스 언어로 변환하는 변환기의 일부이거나 구문 분석기가 소스 언어로 컴파일 단위를 가져 와서이를 분석하고 수정 한 후 수정 된 버전을 동일한 소스 언어로 다시 작성하는 프리 프로세서 인 경우 주석 다른 것들처럼 매우 중요해집니다.

또한 주석에 메타 정보가 있고 특히 JavaDoc과 같은 API 문서를 생성 할 때와 같은 주석에 관심이있는 경우 주석은 갑자기 매우 중요합니다.

여기 주석은 종종 토큰 자체에 첨부됩니다. 주석을 찾으면이를 주석의 주석으로 첨부하십시오. 토큰은 전후에 여러 개의 토큰을 가질 수 있으므로 해당 주석을 처리하는 방법에 따라 목적에 따라 다릅니다.

주석이없는 토큰에 주석을 달려면 문법에서 주석을 모두 제거해야합니다.

구문 분석 트리가 있으면 일부 AST는 고유 한 AST 요소로 각 토큰을 나타내는 주석을 풀기 시작하지만 일반적인 포함 관계 외에 다른 AST 요소에 첨부됩니다. 오픈 소스 IDE에서 사용 가능한 소스 언어에 대한 모든 파서 / AST 구현을 확인하는 것이 좋습니다.

매우 좋은 구현 중 하나는 Java 언어 용 Eclipse 컴파일러 인프라입니다. 그들은 토큰 화하는 동안 주석을 유지하고 내가 기억하는 한 AST 내에서 주석을 나타냅니다. 또한이 파서 / AST 구현은 형식을 유지합니다.

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