niku_ypp
@niku_ypp

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

javascript正規表現

解決したいこと

JavaScriptのコードをKindごとにハイライトしたく、トークン化するためにまず数値にマッチする正規表現を作成したのだが、この正規表現が正しいかを教えていただきたい。

発生している問題・エラー

以下のような正規表現を考えた。

/^[+-]?(?:0b(?:[01]_?)*[01]|0o(?:[0-7]_?)*[0-7]|0x(?:[0-9a-f]_?)*[0-9a-f]|(?:\d_?)*\d(?:\.(?:\d_?)*\d)?(?:e[+-]?(?:\d_?)*\d)?|0\d+)$/i

image (3).png

検証

const regex = /^[+-]?(?:0b(?:[01]_?)*[01]|0o(?:[0-7]_?)*[0-7]|0x(?:[0-9a-f]_?)*[0-9a-f]|(?:\d_?)*\d(?:\.(?:\d_?)*\d)?(?:e[+-]?(?:\d_?)*\d)?|0\d+)$/i;
regex.test(""); // false
regex.test("abc"); // false
regex.test("123abc"); // false
regex.test("0"); // true
regex.test("123456789"); // true
regex.test("123_456_789"); // true
regex.test("1_2_3_4_5_6"); // true
regex.test("1_2_3_"); // false
regex.test("_1_2_3"); // false
regex.test("1__2_3"); // false
regex.test("+123"); // true
regex.test("-123"); // true
regex.test("123.456"); // true
regex.test("-123.456"); // true
regex.test("123.4a6"); // false
regex.test("1_2_3.4_5_6"); // true
regex.test("123_.456"); // false
regex.test("123.4__56"); // false
regex.test("123.456.789"); // false
regex.test("789e3"); // true
regex.test("789e+3"); // true
regex.test("789e-3"); // true
regex.test("789e"); // false
regex.test("1_2_3e4_5_6"); // true
regex.test("123_e456"); // false
regex.test("123e4__56"); // false
regex.test("123.456e789"); // true
regex.test("123.456e-789"); // true 
regex.test("1_2_3.4_5_6e7_8_9"); // true 
regex.test("0b1100"); // true
regex.test("-0b1100"); // true
regex.test("0b1234"); // false
regex.test("0b1100_0110_0101"); // true
regex.test("0b10.1"); // false
regex.test("0b10e1"); // false
regex.test("0o123"); // true
regex.test("0o56789"); // false
regex.test("0o123.456"); // false
regex.test("0o123e456"); // false
regex.test("0123"); // true
regex.test("0_1_2_3"); // true
regex.test("01_2_3"); // true
regex.test("0x123acf"); // true
regex.test("0xabcdefg"); // false
regex.test("0x1_2_3_a_b_c"); // true
regex.test("0x123.456"); // false
regex.test("0x123e"); // true
regex.test("0x123e456"); // true
regex.test("0x123e-456"); // false

これ以外にJavaScript側では数値として認識するが、この正規表現ではマッチできないものや、逆にこの正規表現にだけマッチする文字列があったら教えていただきたい。

0

3Answer

私は isNaN() で判定します。
その後にハイライトするでしょうか?

条件:
文字列の前後に半角空白があること
または、前後に=; () [] /*%(演算子)があること
例 x=253.96/y+3;

0Like

Comments

  1. @niku_ypp

    Questioner

    トークン化は先頭から文字を読んでいくので、トークンの終わりがわからない文字列にはisNaNは使えません。

Comments

  1. @niku_ypp

    Questioner

    以下のようになりました。

    /^[+-]?(?:0b(?:[01]_?)*[01]|0o(?:[0-7]_?)*[0-7]|0x(?:[\da-f]_?)*[\da-f]|(?:[1-9](?:_?\d)*(?:\.(?:\d_?)*\d)?|\.(?:\d_?)*\d)(?:e[+-]?(?:\d_?)*\d)?|0\d*)$/i
    

    image (4).png

  2. 123.とかもあるみたいですね。

NumericLiteral

条件がよくわかりませんが、ECMAScript® 2024では NumericLiteral にて文法が定義されています。

StringNumericLiteral

文字列をパースする処理として捉えるなら、StringNumericLiteral を参考にすべきかもしれません。

StringNumericLiteral では、前後の空白を読み飛ばし、"Infinity" や "-Infinity" を解釈可能なようです。

0Like

Comments

  1. @niku_ypp

    Questioner

    ありがとうございます。一つ上の正規表現であってそうですね。
    BigIntにも対応するにはこんな感じでしょうかね。。。

    /^[+-]?(?:(?:0b(?:[01]_?)*[01]|0o(?:[0-7]_?)*[0-7]|0x(?:[\da-f]_?)*[\da-f])n?|(?:[1-9](?:_?\d)*(?:\.(?:(?:\d_?)*\d)?)?|\.(?:\d_?)*\d)(?:e[+-]?(?:\d_?)*\d)?|[1-9](?:_?\d)*n|0(?:n?|\d+))$/i
    

    image (5).png

Your answer might help someone💌