Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
ECMAScriptを正規表現で解く
@polygon_planet
正規表現で字句解析してみる
var a = 100;
var
a
=
100
;
仕様
ECMA-262
7ᵗʰ Edition / June 2016
ECMAScript® 2016 Language Specification
http://www.ecma-international.org/ecma-262/7.0...
わりと大雑把だけど仕様に
沿った感じで
改行コード (LineTerminator)
/[nru2028u2029]/
<LF> n 0x000A LINE FEED
<CR> r 0x000D CARRIAGE RETURN
<LS> U+2028 LINE SEPARATOR
<...
改行 (LineTerminatorSequence)
/rn|[nru2028u2029]/
空白 (WhiteSpace)
/(?:(?![nru2028u2029])s)+/
<TAB>
<VT>
<FF>
<SP>
<NBSP>
<ZWNBSP>
<USP>
コメント (Comments)
//*[sS]*?*/
|//[^nru2028u2029]*/
<!-- コメント
--> コメント
※ HTML-like Commentsは省略
文字列リテラル (StringLiteral)
/'(?:.|[^'])*'/
'abc'
'ab'c'
'ab
c'
改行にマッチしてしまう
/'(?:[sS]|[^'rn])*'/
'abc'
'ab'c'
'ab
c'
マッチしない
'ab
c' マッチする
/'(?:[sS]|[^'rn])*'/
マッチしない
'aaa<CR><LF>
bbb<CR><LF>
ccc'
/'(?:rn|[sS]|[^'rn])*'/
マッチする
'aaa<CR><LF>
bbb<CR><LF>
ccc'
文字列リテラル (StringLiteral)
/'(?:rn|[sS]|[^'nru2028u20
29])*'|"(?:rn|[sS]|[^"nru
2028u2029])*"/
数値リテラル (NumericLiteral)
/ 0(?:[xX][0-9a-fA-F]+
|[oO][0-7]+
|[bB][01]+
)
| (?:d+(?:.d*)?|.d+)(?:[eE][+-]?d+)?
| [1-9]d*
| 0...
テンプレートリテラル (TemplateLiteral)
/`(?:[sS]|[^`])*`/
`abc`
`ab`c`
`abc${` `}ghi`def
Expressionに対応できてない
正規表現で無限の再帰が必要
/`(?:[sS]|[^`])*`/
/`(?:[sS]|${(?:[sS]|[^{}]|
{(?:[^{}]*(?:{[^{}]*})?)*})*}|[^`
])*`/
` ${
`${
`${
1 + 1
}`
}`
}
`
ある程度のネストまでマッチ
正規表現リテラル (RegularExpressionLiteral)
//(?![*/])(?:[sS]|[^/rn])+
/(?:[gimuy]+b|)/
/a/
/abc/i
//
/**/
/ab/c/
マッチしない
マッチしない
//(?![*/])(?:[sS]|[^/rn])+
/(?:[gimuy]+b|)/
/[/]/ 正しくマッチしない
正規表現リテラル (RegularExpressionLiteral)
//(?![*/])(?:[sS]|[(?:[sS]
|[^]nru2028u2029])*]|[^/nr
u2028u2029])+/(?:[gimuy]+b|)/
/[...
区切り子と演算子 (Punctuators)
/>>>=?|.{3}|<<=|===|!==|>>=|**=|+
+(?=+)|--(?=-)|[=!<>*%+/&|^-
]=|&&||||++|--|<<|>>|=>|**|[-
+*/%<>...
識別子 (Identifier)
/(?:u(?:[0-9a-fA-F]{4}|{[0-9a-fA-
F]+})|[^s+/%*=&|^~<>!?:;,.()[]{
}'"`-])+/
できたパターン
/(/*[sS]*?*/|//[^nru2028u2029]*|<!--[^rnu2028u2029]*|(?:
^|(?:rn|[nru2028u2029]))(?:(?:(?![nru2028u2029])s)+)?-->[...
使い方
var pattern = /.../g;
var code = 'var a = 100';
var tokens = code.match(pattern);
console.log(tokens);
//['var', ' ', ...
RegExp Lookbehind Assertions
肯定的後読み (?<=pattern)
否定的後読み (?<!pattern)
https://github.com/tc39/proposal-regexp-lookbehind
が使...
デモ
http://jsfiddle.net/polygonplanet/mu56y85b/
Upcoming SlideShare
Loading in …5
×

ECMAScriptを正規表現で解く

639 views

Published on

ECMAScriptを正規表現で字句解析します

Published in: Technology
  • Be the first to comment

  • Be the first to like this

ECMAScriptを正規表現で解く

  1. 1. ECMAScriptを正規表現で解く @polygon_planet
  2. 2. 正規表現で字句解析してみる var a = 100; var a = 100 ;
  3. 3. 仕様 ECMA-262 7ᵗʰ Edition / June 2016 ECMAScript® 2016 Language Specification http://www.ecma-international.org/ecma-262/7.0/index.html https://github.com/tc39/ecma262
  4. 4. わりと大雑把だけど仕様に 沿った感じで
  5. 5. 改行コード (LineTerminator) /[nru2028u2029]/ <LF> n 0x000A LINE FEED <CR> r 0x000D CARRIAGE RETURN <LS> U+2028 LINE SEPARATOR <PS> U+2029 PARAGRAPH SEPARATOR
  6. 6. 改行 (LineTerminatorSequence) /rn|[nru2028u2029]/
  7. 7. 空白 (WhiteSpace) /(?:(?![nru2028u2029])s)+/ <TAB> <VT> <FF> <SP> <NBSP> <ZWNBSP> <USP>
  8. 8. コメント (Comments) //*[sS]*?*/ |//[^nru2028u2029]*/ <!-- コメント --> コメント ※ HTML-like Commentsは省略
  9. 9. 文字列リテラル (StringLiteral) /'(?:.|[^'])*'/ 'abc' 'ab'c' 'ab c' 改行にマッチしてしまう
  10. 10. /'(?:[sS]|[^'rn])*'/ 'abc' 'ab'c' 'ab c' マッチしない 'ab c' マッチする
  11. 11. /'(?:[sS]|[^'rn])*'/ マッチしない 'aaa<CR><LF> bbb<CR><LF> ccc'
  12. 12. /'(?:rn|[sS]|[^'rn])*'/ マッチする 'aaa<CR><LF> bbb<CR><LF> ccc'
  13. 13. 文字列リテラル (StringLiteral) /'(?:rn|[sS]|[^'nru2028u20 29])*'|"(?:rn|[sS]|[^"nru 2028u2029])*"/
  14. 14. 数値リテラル (NumericLiteral) / 0(?:[xX][0-9a-fA-F]+ |[oO][0-7]+ |[bB][01]+ ) | (?:d+(?:.d*)?|.d+)(?:[eE][+-]?d+)? | [1-9]d* | 0[0-7]+ /
  15. 15. テンプレートリテラル (TemplateLiteral) /`(?:[sS]|[^`])*`/ `abc` `ab`c`
  16. 16. `abc${` `}ghi`def Expressionに対応できてない 正規表現で無限の再帰が必要 /`(?:[sS]|[^`])*`/
  17. 17. /`(?:[sS]|${(?:[sS]|[^{}]| {(?:[^{}]*(?:{[^{}]*})?)*})*}|[^` ])*`/ ` ${ `${ `${ 1 + 1 }` }` } ` ある程度のネストまでマッチ
  18. 18. 正規表現リテラル (RegularExpressionLiteral) //(?![*/])(?:[sS]|[^/rn])+ /(?:[gimuy]+b|)/ /a/ /abc/i // /**/ /ab/c/ マッチしない マッチしない
  19. 19. //(?![*/])(?:[sS]|[^/rn])+ /(?:[gimuy]+b|)/ /[/]/ 正しくマッチしない
  20. 20. 正規表現リテラル (RegularExpressionLiteral) //(?![*/])(?:[sS]|[(?:[sS] |[^]nru2028u2029])*]|[^/nr u2028u2029])+/(?:[gimuy]+b|)/ /[/]/ マッチする
  21. 21. 区切り子と演算子 (Punctuators) />>>=?|.{3}|<<=|===|!==|>>=|**=|+ +(?=+)|--(?=-)|[=!<>*%+/&|^- ]=|&&||||++|--|<<|>>|=>|**|[- +*/%<>=&|^~!?:;,.()[]{}]/
  22. 22. 識別子 (Identifier) /(?:u(?:[0-9a-fA-F]{4}|{[0-9a-fA- F]+})|[^s+/%*=&|^~<>!?:;,.()[]{ }'"`-])+/
  23. 23. できたパターン /(/*[sS]*?*/|//[^nru2028u2029]*|<!--[^rnu2028u2029]*|(?: ^|(?:rn|[nru2028u2029]))(?:(?:(?![nru2028u2029])s)+)?-->[^n ru2028u2029]*|`(?:[sS]|${(?:[sS]|[^{}]|{(?:[^{}]*(?:{[^{ }]*})?)*})*}|[^`])*`(?=s*(?:(?!s*[/<>*%`^"'w$-])[^/<>*%`^' "({[w$-]|[!=]==?||||&&|/[*/]|[,.;:!?)}]nru2028u2029]|$))|"(?: rn|[sS]|[^"nru2028u2029])*"|'(?:rn|[sS]|[^'nru20 28u2029])*'|(?:/(?![*/])(?:[sS]|[(?:[sS]|[^]nru2028u2 029])*]|[^/nru2028u2029])+/(?:[gimuy]+b|))(?=s*(?:(?!s*[/ <>*%`^"'w$-])[^/<>*%`^'"({[w$-]|[!=]==?||||&&|/[*/]|[,.;:!?)} ]nru2028u2029]|$))|0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)|(?:d +(?:.d*)?|.d+)(?:[eE][+-]?d+)?|[1-9]d*|0[0-7]+|(?:>>>=?|.{3}|<<=| ===|!==|>>=|**=|++(?=+)|--(?=-)|[=!<>*%+/&|^-]=|&&||||++|--|<< |>>|=>|**|[-+*/%<>=&|^~!?:;,.()[]{}])|(?:(?![nru2028u2029])s)+| (?:rn|[nru2028u2029])|(?:u(?:[0-9a-fA-F]{4}|{[0-9a-fA-F]+})|[^ s+/%*=&|^~<>!?:;,.()[]{}'"`-])+)/g
  24. 24. 使い方 var pattern = /.../g; var code = 'var a = 100'; var tokens = code.match(pattern); console.log(tokens); //['var', ' ', 'a', ' ', '=', ' ', '100']
  25. 25. RegExp Lookbehind Assertions 肯定的後読み (?<=pattern) 否定的後読み (?<!pattern) https://github.com/tc39/proposal-regexp-lookbehind が使えるようになったらもう少し厳密にできそう。 ※ Chromeでは実装されている ※ 現在 Stage 2
  26. 26. デモ http://jsfiddle.net/polygonplanet/mu56y85b/

×