ユニコードスカラ値にはサロゲートペアのための領域0xD800-0xDFFFがあり、この範囲は文字を割り当てることがきない。このためcharの範囲からこの部分を外す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
~$ git diff diff --git a/source/src/BNFC/Backend/Haskell/CFtoAlex3.hs b/source/src/BNFC/Backend/Haskell/CFtoAlex3.hs index 054d576..4afdb83 100644 --- a/source/src/BNFC/Backend/Haskell/CFtoAlex3.hs +++ b/source/src/BNFC/Backend/Haskell/CFtoAlex3.hs @@ -63,7 +63,7 @@ cMacros = [ "$s = [a-z\\222-\\255] # [\\247] -- small isolatin1 letter FIXME", "$d = [0-9] -- digit", "$i = [$l $d _ '] -- identifier character", - "$u = [\\0-\\255] -- universal: any character" + "$u = [\\x0000-\\x10FFFF] # [\\xD800 -\\xDFFF] -- universal: any character" ] rMacros :: CF -> [String] ~$ |
1 2 3 4 |
~$ cat R_char.cf LTest. Test::= R_char_sequence; token R_char_sequence (char - [")"])+; ~$ |
BNFCはUTF-8で受け取るため、0xD800を無理やりUTF-8へコンバートする。リトルエンディアンであるので最初の0x0aは改行だ。勝手についてくるがおそらくechoかな。
1 2 3 4 |
~$ echo -e "\x00\x00\xD8\x00\x00\x00\x00" | iconv -f ISO-10646/UCS4 -t ISO-10646/UTF8 - | od -t x4 0000000 0a80a0ed 0000004 ~$ |
0xeda080をBNFCでパースしてみるが、haskellが受け取ってくれない。
1 2 3 4 |
~$ echo -e "\xed\xa0\x80" | ./TestRChar TestRChar: <stdin>: hGetContents: invalid argument (invalid byte sequence) ~$ </stdin> |
サロゲートペア外の文字コードであれば問題なく受け取るのでパースできる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
~$ echo "あ" | od -t x4 0000000 0a8281e3 0000004 ~$ echo "あ" | ./TestRChar Parse Successful! [Abstract Syntax] LTest (R_char_sequence "\12354\n") [Linearized tree] あ ~$ |
BNFCが生成したテスト実行コードを変更してテストしてみる。
1 2 3 4 5 6 7 8 9 10 11 12 |
-- mainのみ抜き出し main :: IO () main = do args < - getArgs case args of ["--help"] -> usage ["--test1"] -> run 2 pTest "\x3042" -- テスト1:正常にパースできるはず「あ」 ["--test2"] -> run 2 pTest "\xD800" -- テスト2:範囲外なのでパースエラーとなるはず。 ["--test3"] -> run 2 pTest "\x2F852" -- テスト3:サロゲートペア範囲の文字「?」 [] -> getContents >>= run 2 pTest "-s":fs -> mapM_ (runFile 0 pTest) fs fs -> mapM_ (runFile 2 pTest) fs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
~$ ./TestRChar --test1 Parse Successful! [Abstract Syntax] LTest (R_char_sequence "\12354") [Linearized tree] あ ~$ ./TestRChar --test2 Parse Failed... Tokens: [Err (Pn 1 1 2)] syntax error at line 1, column 2 due to lexer error ~$ ./TestRChar --test3 Parse Successful! [Abstract Syntax] LTest (R_char_sequence "\194642") [Linearized tree] ? ~$ |
テストが成功したので問題なしかな。