Pegjs: 였λ₯˜ 보고 μž¬μ„€κ³„

에 λ§Œλ“  2013λ…„ 08μ›” 14일  Β·  7μ½”λ©˜νŠΈ  Β·  좜처: pegjs/pegjs

PEG.js의 ν˜„μž¬ 였λ₯˜ 보고 μ‹œμŠ€ν…œμ— μ„Έ 가지 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.

  1. μž‘μ—…μ€ null λ₯Ό λ°˜ν™˜ν•˜μ—¬ 였λ₯˜λ₯Ό λ³΄κ³ ν•©λ‹ˆλ‹€.
Reporting using `null` is inflexible (it doesn't allow to carry any information about the kind of error) and makes it impossible to return `null` as a regular value from actions, which would be useful sometimes (for example [in a JSON parser](https://github.com/dmajda/pegjs/blob/791034fad92c9cd7a9d1c71187df03441bbfd521/examples/json.pegjs#L45)).

#17도 μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.

  1. μ™„μ „νžˆ λ§žμΆ€ν™”λœ λ©”μ‹œμ§€λ‘œ 였λ₯˜λ₯Ό 생성할 방법은 μ—†μŠ΅λ‹ˆλ‹€.
For example, imagine a HTTP 1.1 parser that wants to report an error about missing `Host` header in a HTTP request with a message like "A HTTP 1.1 request must contain a Host header". Currently the only way to do this is to throw an exception with desired message manually. This is cumbersome and it does not interact well with the backtracking behavior (throwing an exception halts the parsing completely, even when it is possible to backtrack and try another alternatives).

  1. $ SyntaxError 의 expected 속성은 κΈ°κ³„μ μœΌλ‘œ μ²˜λ¦¬ν•˜κΈ° μ–΄λ ΅μŠ΅λ‹ˆλ‹€.
The `expected` property of `SyntaxError` is either an array of expectations (each describing one alternative which the parser expected at the position of error) or `null` (meaning that the end of input was expected).

각 κΈ°λŒ€κ°’μ€ λ¬Έμžμ—΄λ‘œ ν‘œμ‹œλ©λ‹ˆλ‹€. 이 λ¬Έμžμ—΄μ€ μ˜ˆμƒλ˜λŠ” λ¦¬ν„°λŸ΄(PEG.js ꡬ문을 μ‚¬μš©ν•˜μ—¬ ν‘œν˜„ - λ”°μ˜΄ν‘œλ‘œ 묢인 λ¬Έμžμ—΄), 문자 클래슀(PEG.js ꡬ문을 μ‚¬μš©ν•˜μ—¬ ν‘œν˜„ - [...] ) λ˜λŠ” λͺ¨λ“  문자(λ¬Έμžμ—΄ "any" 둜 ν‘œν˜„)λ₯Ό μ˜λ―Έν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ 였λ₯˜ 보고 μ‹œμŠ€ν…œμ„ μž¬μ„€κ³„ν•  κ³„νšμž…λ‹ˆλ‹€. λ‚΄κ°€ μƒκ°ν•˜κ³  μžˆλŠ” λ³€κ²½ 사항을 μ„€λͺ…ν•˜κΈ° 전에 ν˜„μž¬ μ‹œμŠ€ν…œμ΄ μ–΄λ–»κ²Œ μž‘λ™ν•˜λŠ”μ§€ μ•½κ°„μ˜ μ„€λͺ…이 ν•„μš”ν•©λ‹ˆλ‹€.

ν˜„μž¬ 였λ₯˜ λ³΄κ³ λŠ” μ–΄λ–»κ²Œ μž‘λ™ν•©λ‹ˆκΉŒ?

PEG.js νŒŒμ„œλŠ” λ¬Έμžμ—΄ λ¦¬ν„°λŸ΄, 문자 클래슀 λ˜λŠ” . 일치λ₯Ό μ‹œλ„ν•˜κ³  μ‹€νŒ¨ν•˜λ©΄ _match failure_λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. _position_ 및 _expectation_(νŒŒμ„œκ°€ μΌμΉ˜μ‹œν‚€λ €κ³  μ‹œλ„ν•œ λ‚΄μš©μ— λŒ€ν•œ μ„€λͺ…)둜 κ΅¬μ„±λ©λ‹ˆλ‹€.

일치 μ‹€νŒ¨λ₯Ό μƒμ„±ν•œ ν›„ νŒŒμ„œλŠ” μ—­μΆ”μ ν•˜κ³  λ‹€λ₯Έ λŒ€μ•ˆμ„ μ‹œλ„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ“€ 쀑 λˆ„κ΅¬λ„ μ„±κ³΅ν•˜μ§€ λͺ»ν•˜κ³  더 이상 μ‹œλ„ν•  것이 μ—†μœΌλ©΄ νŒŒμ„œλŠ” SyntaxError μ˜ˆμ™Έλ₯Ό λ˜μ§‘λ‹ˆλ‹€. 속성(예: μœ„μΉ˜, μ˜ˆμƒ, 였λ₯˜ λ©”μ‹œμ§€ λ“±)을 μ„€μ •ν•  λ•Œ νŒŒμ„œλŠ” κ°€μž₯ λ¨Ό 일치 μ‹€νŒ¨(κ°€μž₯ 큰 μœ„μΉ˜λ₯Ό 가진 것)만 κ³ λ €ν•©λ‹ˆλ‹€. κ·ΈλŸ¬ν•œ μ‹€νŒ¨κ°€ 더 μžˆλ‹€λ©΄ κ·Έλ“€μ˜ κΈ°λŒ€κ°€ ν•©μ³μ§‘λ‹ˆλ‹€.

λͺ…λͺ…λœ κ·œμΉ™μ„ μ‚¬μš©ν•˜λ©΄ 상황이 쑰금 더 λ³΅μž‘ν•΄ μ§€μ§€λ§Œ 이것은 이 λ…Όμ˜μ™€ 관련이 μ—†μŠ΅λ‹ˆλ‹€.

μ œμ•ˆλœ λ³€κ²½ 사항

였λ₯˜ 보고 μ‹œμŠ€ν…œμ˜ λ‹€μŒ λ³€κ²½ 사항에 λŒ€ν•΄ μƒκ°ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

  1. SyntaxError.expected 의 κΈ°λŒ€μΉ˜λŠ” λ¬Έμžμ—΄μ΄ μ•„λ‹ˆλΌ 객체둜 ν‘œν˜„λ©λ‹ˆλ‹€. κ°œμ²΄μ—λŠ” "literal" , "class" , "any" , "eof" 와 같은 값이 μžˆλŠ” type 속성이 μžˆμ–΄ κΈ°λŒ€ μœ ν˜•μ„ κ²°μ •ν•©λ‹ˆλ‹€. 일뢀 κΈ°λŒ€ μœ ν˜•μ˜ 경우 λ‹€λ₯Έ 속성에 μ„ΈλΆ€ 정보가 ν¬ν•¨λ©λ‹ˆλ‹€(예: "literal" κΈ°λŒ€μ˜ 경우 μ˜ˆμƒ λ¬Έμžμ—΄μ΄ ν¬ν•¨λœ value 속성). 이것은 κΈ°λŒ€μΉ˜μ˜ 기계적 처리λ₯Ό λ‹¨μˆœν™”ν•  κ²ƒμž…λ‹ˆλ‹€.

type μ†μ„±μ˜ λŒ€μ•ˆμ€ 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ type 속성은 μ‚¬μš©μžκ°€ 닀루기 더 μ‰¬μšΈ 것이라고 μƒκ°ν•©λ‹ˆλ‹€.

  1. null λ₯Ό λ°˜ν™˜ν•˜λŠ” μž‘μ—…μ΄ ν—ˆμš©λ©λ‹ˆλ‹€. μ΄λŠ” 일반 값이며 였λ₯˜λ₯Ό λ‚˜νƒ€λ‚΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  2. μ•‘μ…˜μ€ μƒˆλ‘œμš΄ error ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 맀치 μ‹€νŒ¨λ₯Ό μœ λ°œν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ§€κ°œλ³€μˆ˜λ‘œ 였λ₯˜ λ©”μ‹œμ§€λ₯Ό λ°›μŠ΅λ‹ˆλ‹€. 이 κΈ°λŠ₯에 μ˜ν•΄ 트리거된 μ‹€νŒ¨(_맞좀 일치 μ‹€νŒ¨_라고 함)λŠ” _μœ„μΉ˜_ 및 _였λ₯˜ λ©”μ‹œμ§€_둜 κ΅¬μ„±λ©λ‹ˆλ‹€. 그듀은 μ–΄λ–€ κΈ°λŒ€λ„ ν•˜μ§€ μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€.

error ν•¨μˆ˜λŠ” μž‘μ—… 싀행을 μ€‘λ‹¨ν•˜μ§€ μ•Šκ³  μ‹€νŒ¨λ‘œ ν‘œμ‹œν•˜κ³  였λ₯˜ λ©”μ‹œμ§€λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€. μ‹€μ œ μ‹€νŒ¨λŠ” μž‘μ—… 싀행이 μ™„λ£Œλœ ν›„μ—λ§Œ μƒμ„±λ©λ‹ˆλ‹€. error ν•¨μˆ˜κ°€ μ—¬λŸ¬ 번 호좜되면 λ§ˆμ§€λ§‰ 호좜이 μš°μ„ ν•©λ‹ˆλ‹€(ν•΄λ‹Ή 였λ₯˜ λ©”μ‹œμ§€κ°€ μ‚¬μš©λ¨).

μ‚¬μš©μž 지정 일치 μ‹€νŒ¨λŠ” 일반 일치 μ‹€νŒ¨μ²˜λŸΌ μ²˜λ¦¬λ©λ‹ˆλ‹€. 즉, ꡬ문 뢄석을 μ™„μ „νžˆ μ€‘λ‹¨ν•˜μ§€ μ•Šκ³  νŒŒμ„œκ°€ μ—­μΆ”μ ν•˜μ—¬ λ‹€λ₯Έ λŒ€μ•ˆμ„ μ‹œλ„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ ν•œ 가지 차이점이 μžˆμŠ΅λ‹ˆλ‹€. λ§ˆμΉ¨λ‚΄ SyntaxError μ˜ˆμ™Έλ₯Ό throwν•  λ•Œ 일반 일치 μ‹€νŒ¨μ— μ μš©λ˜λŠ” μ˜ˆμƒ μ‘°ν•© κ·œμΉ™μ΄ μ‚¬μš©μž 지정 κ·œμΉ™μ— μ μš©λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ°€μž₯ λ¨Ό μœ„μΉ˜μ˜ 일치 μ‹€νŒ¨ μ„ΈνŠΈμ— ν•˜λ‚˜ μ΄μƒμ˜ μ‚¬μš©μž 지정 ν•­λͺ©μ΄ μžˆλŠ” 경우 일반 ν•­λͺ©μ„ μ™„μ „νžˆ λ¬΄μ‹œν•©λ‹ˆλ‹€. μ‚¬μš©μž μ •μ˜ μ‹€νŒ¨κ°€ 더 있으면 λ§ˆμ§€λ§‰μ— μƒμ„±λœ μ‹€νŒ¨κ°€ μŠΉλ¦¬ν•©λ‹ˆλ‹€.

μ‚¬μš©μž 지정 일치 μ‹€νŒ¨λ₯Ό 기반으둜 ν•˜λŠ” SyntaxError μ˜ˆμ™ΈλŠ” 일반 μ‹€νŒ¨λ₯Ό 기반으둜 ν•˜λŠ” μ˜ˆμ™Έμ™€ λ‹€λ¦…λ‹ˆλ‹€. message 속성은 μ‹€νŒ¨ 였λ₯˜ λ©”μ‹œμ§€μ™€ κ°™κ³  expected 속성은 null μž…λ‹ˆλ‹€.

μ˜ˆμ‹œ

```
μ‹œμž‘ = 기호:[+-]? 숫자:[0-9]+ {
var 결과 = parseInt((기호 || "") + 숫자.join(""), 10);

 if (result % 2 == 0) {
   error("The number must be an odd integer.");
 }

 return result;

}
```

2 μž…λ ₯ μ‹œ μœ„μ˜ λ¬Έλ²•μ—μ„œ μƒμ„±λœ νŒŒμ„œλŠ” SyntaxError message κ°€ "The number must be an odd integer." 둜 μ„€μ •λ˜κ³  expected κ°€ $둜 μ„€μ •λœ null #$9$#$λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

  1. μ•‘μ…˜μ€ expected ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 일반 일치 μ‹€νŒ¨λ₯Ό νŠΈλ¦¬κ±°ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μ˜ˆμƒ κ°’ μ„€λͺ…을 λ§€κ°œλ³€μˆ˜λ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€. 이 κΈ°λŠ₯은 전체 였λ₯˜ λ©”μ‹œμ§€λ₯Ό 생성할 ν•„μš”κ°€ μ—†κ³  μžλ™μœΌλ‘œ "μ˜ˆμƒ _X_ν•˜μ§€λ§Œ "2"κ°€ 발견됨" ν˜•μ‹μ„ 생성할 ν•„μš”κ°€ μ—†λŠ” 상황에 λŒ€ν•œ 편의λ₯Ό μœ„ν•΄ 주둜 μ œκ³΅λ©λ‹ˆλ‹€. μΆ©λΆ„ν•©λ‹ˆλ‹€.

expected ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ 일치 μ‹€νŒ¨λ₯Ό 기반으둜 ν•˜λŠ” SyntaxError μ˜ˆμ™ΈλŠ” 일반 μ‹€νŒ¨λ₯Ό 기반으둜 ν•˜λŠ” μ˜ˆμ™Έμ™€ μœ μ‚¬ν•©λ‹ˆλ‹€.

μ˜ˆμ‹œ

```
μ‹œμž‘ = 기호:[+-]? 숫자:[0-9]+ {
var 결과 = parseInt((기호 || "") + 숫자.join(""), 10);

 if (result % 2 == 0) {
   expected("odd integer");
 }

 return result;

}
```

μž…λ ₯ 2 μ—μ„œ μœ„μ˜ λ¬Έλ²•μ—μ„œ μƒμ„±λœ νŒŒμ„œλŠ” SyntaxError λ₯Ό μƒμ„±ν•˜κ³  $ message λŠ” "Expected odd integer but "2" found." 둜 μ„€μ •λ˜κ³  expected λŠ” [ { type: "user", description: "odd integer" } ] 둜 μ„€μ •λ©λ‹ˆλ‹€.

λ‹€μŒ 단계

μ œμ•ˆλœ λ³€κ²½ 사항에 λŒ€ν•œ λͺ¨λ“  λ©”λͺ¨λ₯Ό ν™˜μ˜ν•©λ‹ˆλ‹€. 의견으둜 μΆ”κ°€ν•˜μ‹­μ‹œμ˜€. 곧 μ œμ•ˆ(λ˜λŠ” ν”Όλ“œλ°±μ— 따라 일뢀 μˆ˜μ •λœ 버전) κ΅¬ν˜„μ„ μ‹œμž‘ν•  κ³„νšμž…λ‹ˆλ‹€.

feature

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

그럼 아직 "κ²½κ³ " κΈ°λŠ₯은 μ—†λŠ” κ±΄κ°€μš”?

λͺ¨λ“  7 λŒ“κΈ€

였λ₯˜ κΈ°λŠ₯을 μ—¬λŸ¬ 번 ν˜ΈμΆœν•˜λ©΄ μ—¬λŸ¬ 였λ₯˜κ°€ λ°œμƒν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 그런 λ‹€μŒ κ°€λŠ₯ν•œ ν•œ 많이 ꡬ문 뢄석을 계속할 수 μžˆμŠ΅λ‹ˆλ‹€.

string = '"' value:(!(eol / '"') .)+ '"' { return value; }
       / '"' value:(!(eol / '"') .)+     { error('unterminated string constant'); return value; }

경고에 λŒ€ν•œ 지원도 μΆ”κ°€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

였λ₯˜ κΈ°λŠ₯을 μ—¬λŸ¬ 번 ν˜ΈμΆœν•˜λ©΄ μ—¬λŸ¬ 였λ₯˜κ°€ λ°œμƒν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 그런 λ‹€μŒ κ°€λŠ₯ν•œ ν•œ 많이 ꡬ문 뢄석을 계속할 수 μžˆμŠ΅λ‹ˆλ‹€.

이것이 ν•„μš”ν•œ μ‚¬μš© μ‚¬λ‘€μ˜ 이름을 μ•Œλ €μ£Όμ‹œκ² μŠ΅λ‹ˆκΉŒ? 당신이 μ œκ³΅ν•œ μ˜ˆκ°€ λ‚΄ μ œμ•ˆμ—λ„ 적용될 것 κ°™μŠ΅λ‹ˆλ‹€.

이미 λͺ‡ 가지 μ‚¬μš© 사둀가 μžˆμ§€λ§Œ μ–Όλ§ˆλ‚˜ λŒ€ν‘œμ μΈμ§€ 잘 λͺ°λΌμ„œ 더 보고 μ‹ΆμŠ΅λ‹ˆλ‹€.

경고에 λŒ€ν•œ 지원도 μΆ”κ°€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

저도 μƒκ°μ€‘μž…λ‹ˆλ‹€.

μ—¬λŸ¬ 였λ₯˜ 및 경고의 λ¬Έμ œλŠ” λ‹¨μˆœν•˜κ³  직관적인 " parse λŠ” 성곡 μ‹œ 일뢀 값을 λ°˜ν™˜ν•˜κ³  였λ₯˜ μ‹œ μ˜ˆμ™Έλ₯Ό λ°˜ν™˜"ν•˜λŠ” κ²ƒκ³ΌλŠ” λ‹€λ₯Έ μΈν„°νŽ˜μ΄μŠ€κ°€ ν•„μš”ν•˜λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. νŒŒμ„œλŠ” μ‹€νŒ¨ν•œ ꡬ문 뢄석에 λŒ€ν•œ μ—¬λŸ¬ 였λ₯˜μ™€ 성곡적인 ꡬ문 뢄석 및 μ‹€νŒ¨ν•œ ꡬ문 뢄석 λͺ¨λ‘μ— λŒ€ν•œ κ²½κ³ λ₯Ό 보고해야 ν•©λ‹ˆλ‹€.

μ—¬κΈ°μ„œ κ°€μž₯ 직관적인 APIλŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ? λ‹€μ‹œ λ§ν•˜μ§€λ§Œ, λ‚˜λŠ” λͺ‡ 가지 아이디어가 μžˆμ§€λ§Œ λ‹€λ₯Έ μ‚¬λžŒλ“€μ€ μ–΄λ–»κ²Œ μƒκ°ν•˜λŠ”μ§€ μ•Œκ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

이것이 ν•„μš”ν•œ μ‚¬μš© μ‚¬λ‘€μ˜ 이름을 μ•Œλ €μ£Όμ‹œκ² μŠ΅λ‹ˆκΉŒ? 당신이 μ œκ³΅ν•œ μ˜ˆκ°€ λ‚΄ μ œμ•ˆμ—λ„ 적용될 것 κ°™μŠ΅λ‹ˆλ‹€.

μ €μ˜ μ£Όμš” μ‚¬μš© μ‚¬λ‘€λŠ” 치λͺ…적이지 μ•Šμ€ ꡬ문 뢄석 였λ₯˜μž…λ‹ˆλ‹€. μ’…λ£Œλ˜μ§€ μ•Šμ€ λ¬Έμžμ—΄, 숫자둜 μ‹œμž‘ν•˜λŠ” μ‹λ³„μž, 쀑첩 주석, μ„Έλ―Έμ½œλ‘  λˆ„λ½ λ“±

일반적으둜 κ°€λŠ₯ν•œ ν•œ λ§Žμ€ 였λ₯˜κ°€ μ‚¬μš©μžμ—κ²Œ ν‘œμ‹œλ  수 μžˆλ„λ‘ νŒŒμ„œλ₯Ό μ΅œλŒ€ν•œ μ§„ν–‰μ‹œν‚€λŠ” 것이 κ°€μž₯ μ’‹μŠ΅λ‹ˆλ‹€. νŒŒμ„œκ°€ ꡬ문 뢄석을 끝내고 λ‹€μŒ 단계(예: 컴파일)μ—μ„œλ„ 였λ₯˜λ₯Ό 보고할 수 μžˆλ‹€λ©΄ 쒋을 κ²ƒμž…λ‹ˆλ‹€.

이제 κ΅¬ν˜„ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. tools/impact μŠ€ν¬λ¦½νŠΈλŠ” 전체 컀밋 μ„ΈνŠΈμ˜ λ‹€μŒκ³Ό 같은 μ„±λŠ₯ 영ν–₯을 λ³΄κ³ ν•©λ‹ˆλ‹€.

Speed impact
------------
Before:     1144.21 kB/s
After:      999.89 kB/s
Difference: -12.62%

Size impact
-----------
Before:     863523 b
After:      1019968 b
Difference: 18.11%

(Measured by /tools/impact with Node.js v0.6.18 on x86_64 GNU/Linux.)

12.62% 속도 νŒ¨λ„ν‹°μ™€ 18.11% 크기 νŒ¨λ„ν‹°λŠ” μ΄λŸ¬ν•œ 였랜 문제 집합을 ν•΄κ²°ν•˜λŠ” 데 μ ν•©ν•˜λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

폐쇄.

@dmajda : 쒋은 μ†Œμ‹μž…λ‹ˆλ‹€! null 이 더 이상 μ‹€νŒ¨ μ‹ ν˜Έλ₯Ό 보내지 μ•Šμ•„ κΈ°μ©λ‹ˆλ‹€.

그럼 아직 "κ²½κ³ " κΈ°λŠ₯은 μ—†λŠ” κ±΄κ°€μš”?

κ²½κ³  κΈ°λŠ₯ μ£Όμ œλŠ” #325μ—μ„œ μΆ”μ λ©λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰