PEG.jsμ νμ¬ μ€λ₯ λ³΄κ³ μμ€ν μ μΈ κ°μ§ λ¬Έμ κ° μμ΅λλ€.
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λ μ°Έμ‘°νμμμ€.
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).
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
μμΈλ₯Ό λμ§λλ€. μμ±(μ: μμΉ, μμ, μ€λ₯ λ©μμ§ λ±)μ μ€μ ν λ νμλ κ°μ₯ λ¨Ό μΌμΉ μ€ν¨(κ°μ₯ ν° μμΉλ₯Ό κ°μ§ κ²)λ§ κ³ λ €ν©λλ€. κ·Έλ¬ν μ€ν¨κ° λ μλ€λ©΄ κ·Έλ€μ κΈ°λκ° ν©μ³μ§λλ€.
λͺ λͺ λ κ·μΉμ μ¬μ©νλ©΄ μν©μ΄ μ‘°κΈ λ 볡μ‘ν΄ μ§μ§λ§ μ΄κ²μ μ΄ λ Όμμ κ΄λ ¨μ΄ μμ΅λλ€.
μ€λ₯ λ³΄κ³ μμ€ν μ λ€μ λ³κ²½ μ¬νμ λν΄ μκ°νκ³ μμ΅λλ€.
SyntaxError.expected
μ κΈ°λμΉλ λ¬Έμμ΄μ΄ μλλΌ κ°μ²΄λ‘ ννλ©λλ€. κ°μ²΄μλ "literal"
, "class"
, "any"
, "eof"
μ κ°μ κ°μ΄ μλ type
μμ±μ΄ μμ΄ κΈ°λ μ νμ κ²°μ ν©λλ€. μΌλΆ κΈ°λ μ νμ κ²½μ° λ€λ₯Έ μμ±μ μΈλΆ μ λ³΄κ° ν¬ν¨λ©λλ€(μ: "literal"
κΈ°λμ κ²½μ° μμ λ¬Έμμ΄μ΄ ν¬ν¨λ value
μμ±). μ΄κ²μ κΈ°λμΉμ κΈ°κ³μ μ²λ¦¬λ₯Ό λ¨μνν κ²μ
λλ€.type
μμ±μ λμμ ν΄λμ€λ₯Ό μ¬μ©νλ κ²μ
λλ€. νμ§λ§ type
μμ±μ μ¬μ©μκ° λ€λ£¨κΈ° λ μ¬μΈ κ²μ΄λΌκ³ μκ°ν©λλ€.
null
λ₯Ό λ°ννλ μμ
μ΄ νμ©λ©λλ€. μ΄λ μΌλ° κ°μ΄λ©° μ€λ₯λ₯Ό λνλ΄μ§ μμ΅λλ€.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$#$λ₯Ό μμ±ν©λλ€.
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" } ]
λ‘ μ€μ λ©λλ€.
μ μλ λ³κ²½ μ¬νμ λν λͺ¨λ λ©λͺ¨λ₯Ό νμν©λλ€. μ견μΌλ‘ μΆκ°νμμμ€. 곧 μ μ(λλ νΌλλ°±μ λ°λΌ μΌλΆ μμ λ λ²μ ) ꡬνμ μμν κ³νμ λλ€.
μ€λ₯ κΈ°λ₯μ μ¬λ¬ λ² νΈμΆνλ©΄ μ¬λ¬ μ€λ₯κ° λ°μνλ κ²μ΄ μ’μ΅λλ€. κ·Έλ° λ€μ κ°λ₯ν ν λ§μ΄ ꡬ문 λΆμμ κ³μν μ μμ΅λλ€.
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μμ μΆμ λ©λλ€.
κ°μ₯ μ μ©ν λκΈ
κ·ΈλΌ μμ§ "κ²½κ³ " κΈ°λ₯μ μλ 건κ°μ?