Parent Directory
|
Revision Log
|
Patch
| revision 1.149 by wakaba, Sun May 25 08:53:49 2008 UTC | revision 1.172 by wakaba, Sun Sep 14 03:07:58 2008 UTC | |
|---|---|---|
| # | Line 45 sub MISC_SPECIAL_EL () { 0b1000000000000 | Line 45 sub MISC_SPECIAL_EL () { 0b1000000000000 |
| 45 | sub FOREIGN_EL () { 0b10000000000000000000000000 } | sub FOREIGN_EL () { 0b10000000000000000000000000 } |
| 46 | sub FOREIGN_FLOW_CONTENT_EL () { 0b100000000000000000000000000 } | sub FOREIGN_FLOW_CONTENT_EL () { 0b100000000000000000000000000 } |
| 47 | sub MML_AXML_EL () { 0b1000000000000000000000000000 } | sub MML_AXML_EL () { 0b1000000000000000000000000000 } |
| 48 | sub RUBY_EL () { 0b10000000000000000000000000000 } | |
| 49 | sub RUBY_COMPONENT_EL () { 0b100000000000000000000000000000 } | |
| 50 | ||
| 51 | sub TABLE_ROWS_EL () { | sub TABLE_ROWS_EL () { |
| 52 | TABLE_EL | | TABLE_EL | |
| # | Line 52 sub TABLE_ROWS_EL () { | Line 54 sub TABLE_ROWS_EL () { |
| 54 | TABLE_ROW_GROUP_EL | TABLE_ROW_GROUP_EL |
| 55 | } | } |
| 56 | ||
| 57 | ## NOTE: Used in "generate implied end tags" algorithm. | |
| 58 | ## NOTE: There is a code where a modified version of END_TAG_OPTIONAL_EL | |
| 59 | ## is used in "generate implied end tags" implementation (search for the | |
| 60 | ## function mae). | |
| 61 | sub END_TAG_OPTIONAL_EL () { | sub END_TAG_OPTIONAL_EL () { |
| 62 | DD_EL | | DD_EL | |
| 63 | DT_EL | | DT_EL | |
| 64 | LI_EL | | LI_EL | |
| 65 | P_EL | P_EL | |
| 66 | RUBY_COMPONENT_EL | |
| 67 | } | } |
| 68 | ||
| 69 | ## NOTE: Used in </body> and EOF algorithms. | |
| 70 | sub ALL_END_TAG_OPTIONAL_EL () { | sub ALL_END_TAG_OPTIONAL_EL () { |
| 71 | END_TAG_OPTIONAL_EL | | DD_EL | |
| 72 | DT_EL | | |
| 73 | LI_EL | | |
| 74 | P_EL | | |
| 75 | ||
| 76 | BODY_EL | | BODY_EL | |
| 77 | HTML_EL | | HTML_EL | |
| 78 | TABLE_CELL_EL | | TABLE_CELL_EL | |
| # | Line 96 sub SPECIAL_EL () { | Line 108 sub SPECIAL_EL () { |
| 108 | ADDRESS_EL | | ADDRESS_EL | |
| 109 | BODY_EL | | BODY_EL | |
| 110 | DIV_EL | | DIV_EL | |
| 111 | END_TAG_OPTIONAL_EL | | |
| 112 | DD_EL | | |
| 113 | DT_EL | | |
| 114 | LI_EL | | |
| 115 | P_EL | | |
| 116 | ||
| 117 | FORM_EL | | FORM_EL | |
| 118 | FRAMESET_EL | | FRAMESET_EL | |
| 119 | HEADING_EL | | HEADING_EL | |
| # | Line 170 my $el_category = { | Line 187 my $el_category = { |
| 187 | param => MISC_SPECIAL_EL, | param => MISC_SPECIAL_EL, |
| 188 | plaintext => MISC_SPECIAL_EL, | plaintext => MISC_SPECIAL_EL, |
| 189 | pre => MISC_SPECIAL_EL, | pre => MISC_SPECIAL_EL, |
| 190 | rp => RUBY_COMPONENT_EL, | |
| 191 | rt => RUBY_COMPONENT_EL, | |
| 192 | ruby => RUBY_EL, | |
| 193 | s => FORMATTING_EL, | s => FORMATTING_EL, |
| 194 | script => MISC_SPECIAL_EL, | script => MISC_SPECIAL_EL, |
| 195 | select => SELECT_EL, | select => SELECT_EL, |
| # | Line 334 sub parse_byte_string ($$$$;$) { | Line 354 sub parse_byte_string ($$$$;$) { |
| 354 | return $self->parse_byte_stream ($charset_name, $input, @_[1..$#_]); | return $self->parse_byte_stream ($charset_name, $input, @_[1..$#_]); |
| 355 | } # parse_byte_string | } # parse_byte_string |
| 356 | ||
| 357 | sub parse_byte_stream ($$$$;$) { | sub parse_byte_stream ($$$$;$$) { |
| 358 | # my ($self, $charset_name, $byte_stream, $doc, $onerror, $get_wrapper) = @_; | |
| 359 | my $self = ref $_[0] ? shift : shift->new; | my $self = ref $_[0] ? shift : shift->new; |
| 360 | my $charset_name = shift; | my $charset_name = shift; |
| 361 | my $byte_stream = $_[0]; | my $byte_stream = $_[0]; |
| # | Line 345 sub parse_byte_stream ($$$$;$) { | Line 366 sub parse_byte_stream ($$$$;$) { |
| 366 | }; | }; |
| 367 | $self->{parse_error} = $onerror; # updated later by parse_char_string | $self->{parse_error} = $onerror; # updated later by parse_char_string |
| 368 | ||
| 369 | my $get_wrapper = $_[3] || sub ($) { | |
| 370 | return $_[0]; # $_[0] = byte stream handle, returned = arg to char handle | |
| 371 | }; | |
| 372 | ||
| 373 | ## HTML5 encoding sniffing algorithm | ## HTML5 encoding sniffing algorithm |
| 374 | require Message::Charset::Info; | require Message::Charset::Info; |
| 375 | my $charset; | my $charset; |
| # | Line 352 sub parse_byte_stream ($$$$;$) { | Line 377 sub parse_byte_stream ($$$$;$) { |
| 377 | my ($char_stream, $e_status); | my ($char_stream, $e_status); |
| 378 | ||
| 379 | SNIFFING: { | SNIFFING: { |
| 380 | ## NOTE: By setting |allow_fallback| option true when the | |
| 381 | ## |get_decode_handle| method is invoked, we ignore what the HTML5 | |
| 382 | ## spec requires, i.e. unsupported encoding should be ignored. | |
| 383 | ## TODO: We should not do this unless the parser is invoked | |
| 384 | ## in the conformance checking mode, in which this behavior | |
| 385 | ## would be useful. | |
| 386 | ||
| 387 | ## Step 1 | ## Step 1 |
| 388 | if (defined $charset_name) { | if (defined $charset_name) { |
| 389 | $charset = Message::Charset::Info->get_by_iana_name ($charset_name); | $charset = Message::Charset::Info->get_by_html_name ($charset_name); |
| 390 | ## TODO: Is this ok? Transfer protocol's parameter should be | |
| 391 | ## interpreted in its semantics? | |
| 392 | ||
| 393 | ## ISSUE: Unsupported encoding is not ignored according to the spec. | ## ISSUE: Unsupported encoding is not ignored according to the spec. |
| 394 | ($char_stream, $e_status) = $charset->get_decode_handle | ($char_stream, $e_status) = $charset->get_decode_handle |
| # | Line 379 sub parse_byte_stream ($$$$;$) { | Line 412 sub parse_byte_stream ($$$$;$) { |
| 412 | ||
| 413 | ## Step 3 | ## Step 3 |
| 414 | if ($byte_buffer =~ /^\xFE\xFF/) { | if ($byte_buffer =~ /^\xFE\xFF/) { |
| 415 | $charset = Message::Charset::Info->get_by_iana_name ('utf-16be'); | $charset = Message::Charset::Info->get_by_html_name ('utf-16be'); |
| 416 | ($char_stream, $e_status) = $charset->get_decode_handle | ($char_stream, $e_status) = $charset->get_decode_handle |
| 417 | ($byte_stream, allow_error_reporting => 1, | ($byte_stream, allow_error_reporting => 1, |
| 418 | allow_fallback => 1, byte_buffer => \$byte_buffer); | allow_fallback => 1, byte_buffer => \$byte_buffer); |
| 419 | $self->{confident} = 1; | $self->{confident} = 1; |
| 420 | last SNIFFING; | last SNIFFING; |
| 421 | } elsif ($byte_buffer =~ /^\xFF\xFE/) { | } elsif ($byte_buffer =~ /^\xFF\xFE/) { |
| 422 | $charset = Message::Charset::Info->get_by_iana_name ('utf-16le'); | $charset = Message::Charset::Info->get_by_html_name ('utf-16le'); |
| 423 | ($char_stream, $e_status) = $charset->get_decode_handle | ($char_stream, $e_status) = $charset->get_decode_handle |
| 424 | ($byte_stream, allow_error_reporting => 1, | ($byte_stream, allow_error_reporting => 1, |
| 425 | allow_fallback => 1, byte_buffer => \$byte_buffer); | allow_fallback => 1, byte_buffer => \$byte_buffer); |
| 426 | $self->{confident} = 1; | $self->{confident} = 1; |
| 427 | last SNIFFING; | last SNIFFING; |
| 428 | } elsif ($byte_buffer =~ /^\xEF\xBB\xBF/) { | } elsif ($byte_buffer =~ /^\xEF\xBB\xBF/) { |
| 429 | $charset = Message::Charset::Info->get_by_iana_name ('utf-8'); | $charset = Message::Charset::Info->get_by_html_name ('utf-8'); |
| 430 | ($char_stream, $e_status) = $charset->get_decode_handle | ($char_stream, $e_status) = $charset->get_decode_handle |
| 431 | ($byte_stream, allow_error_reporting => 1, | ($byte_stream, allow_error_reporting => 1, |
| 432 | allow_fallback => 1, byte_buffer => \$byte_buffer); | allow_fallback => 1, byte_buffer => \$byte_buffer); |
| # | Line 412 sub parse_byte_stream ($$$$;$) { | Line 445 sub parse_byte_stream ($$$$;$) { |
| 445 | $charset_name = Whatpm::Charset::UniversalCharDet->detect_byte_string | $charset_name = Whatpm::Charset::UniversalCharDet->detect_byte_string |
| 446 | ($byte_buffer); | ($byte_buffer); |
| 447 | if (defined $charset_name) { | if (defined $charset_name) { |
| 448 | $charset = Message::Charset::Info->get_by_iana_name ($charset_name); | $charset = Message::Charset::Info->get_by_html_name ($charset_name); |
| 449 | ||
| 450 | ## ISSUE: Unsupported encoding is not ignored according to the spec. | ## ISSUE: Unsupported encoding is not ignored according to the spec. |
| 451 | require Whatpm::Charset::DecodeHandle; | require Whatpm::Charset::DecodeHandle; |
| # | Line 423 sub parse_byte_stream ($$$$;$) { | Line 456 sub parse_byte_stream ($$$$;$) { |
| 456 | allow_fallback => 1, byte_buffer => \$byte_buffer); | allow_fallback => 1, byte_buffer => \$byte_buffer); |
| 457 | if ($char_stream) { | if ($char_stream) { |
| 458 | $buffer->{buffer} = $byte_buffer; | $buffer->{buffer} = $byte_buffer; |
| 459 | !!!parse-error (type => 'sniffing:chardet', ## TODO: type name | !!!parse-error (type => 'sniffing:chardet', |
| 460 | value => $charset_name, | text => $charset_name, |
| 461 | level => $self->{info_level}, | level => $self->{level}->{info}, |
| 462 | layer => 'encode', | |
| 463 | line => 1, column => 1); | line => 1, column => 1); |
| 464 | $self->{confident} = 0; | $self->{confident} = 0; |
| 465 | last SNIFFING; | last SNIFFING; |
| # | Line 434 sub parse_byte_stream ($$$$;$) { | Line 468 sub parse_byte_stream ($$$$;$) { |
| 468 | ||
| 469 | ## Step 7: default | ## Step 7: default |
| 470 | ## TODO: Make this configurable. | ## TODO: Make this configurable. |
| 471 | $charset = Message::Charset::Info->get_by_iana_name ('windows-1252'); | $charset = Message::Charset::Info->get_by_html_name ('windows-1252'); |
| 472 | ## NOTE: We choose |windows-1252| here, since |utf-8| should be | ## NOTE: We choose |windows-1252| here, since |utf-8| should be |
| 473 | ## detectable in the step 6. | ## detectable in the step 6. |
| 474 | require Whatpm::Charset::DecodeHandle; | require Whatpm::Charset::DecodeHandle; |
| # | Line 446 sub parse_byte_stream ($$$$;$) { | Line 480 sub parse_byte_stream ($$$$;$) { |
| 480 | allow_fallback => 1, | allow_fallback => 1, |
| 481 | byte_buffer => \$byte_buffer); | byte_buffer => \$byte_buffer); |
| 482 | $buffer->{buffer} = $byte_buffer; | $buffer->{buffer} = $byte_buffer; |
| 483 | !!!parse-error (type => 'sniffing:default', ## TODO: type name | !!!parse-error (type => 'sniffing:default', |
| 484 | value => 'windows-1252', | text => 'windows-1252', |
| 485 | level => $self->{info_level}, | level => $self->{level}->{info}, |
| 486 | line => 1, column => 1); | line => 1, column => 1, |
| 487 | layer => 'encode'); | |
| 488 | $self->{confident} = 0; | $self->{confident} = 0; |
| 489 | } # SNIFFING | } # SNIFFING |
| 490 | ||
| $self->{input_encoding} = $charset->get_iana_name; | ||
| 491 | if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) { | if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) { |
| 492 | !!!parse-error (type => 'chardecode:fallback', ## TODO: type name | $self->{input_encoding} = $charset->get_iana_name; ## TODO: Should we set actual charset decoder's encoding name? |
| 493 | value => $self->{input_encoding}, | !!!parse-error (type => 'chardecode:fallback', |
| 494 | level => $self->{unsupported_level}, | #text => $self->{input_encoding}, |
| 495 | line => 1, column => 1); | level => $self->{level}->{uncertain}, |
| 496 | line => 1, column => 1, | |
| 497 | layer => 'encode'); | |
| 498 | } elsif (not ($e_status & | } elsif (not ($e_status & |
| 499 | Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) { | Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) { |
| 500 | !!!parse-error (type => 'chardecode:no error', ## TODO: type name | $self->{input_encoding} = $charset->get_iana_name; |
| 501 | value => $self->{input_encoding}, | !!!parse-error (type => 'chardecode:no error', |
| 502 | level => $self->{unsupported_level}, | text => $self->{input_encoding}, |
| 503 | line => 1, column => 1); | level => $self->{level}->{uncertain}, |
| 504 | line => 1, column => 1, | |
| 505 | layer => 'encode'); | |
| 506 | } else { | |
| 507 | $self->{input_encoding} = $charset->get_iana_name; | |
| 508 | } | } |
| 509 | ||
| 510 | $self->{change_encoding} = sub { | $self->{change_encoding} = sub { |
| # | Line 472 sub parse_byte_stream ($$$$;$) { | Line 512 sub parse_byte_stream ($$$$;$) { |
| 512 | $charset_name = shift; | $charset_name = shift; |
| 513 | my $token = shift; | my $token = shift; |
| 514 | ||
| 515 | $charset = Message::Charset::Info->get_by_iana_name ($charset_name); | $charset = Message::Charset::Info->get_by_html_name ($charset_name); |
| 516 | ($char_stream, $e_status) = $charset->get_decode_handle | ($char_stream, $e_status) = $charset->get_decode_handle |
| 517 | ($byte_stream, allow_error_reporting => 1, allow_fallback => 1, | ($byte_stream, allow_error_reporting => 1, allow_fallback => 1, |
| 518 | byte_buffer => \ $buffer->{buffer}); | byte_buffer => \ $buffer->{buffer}); |
| # | Line 483 sub parse_byte_stream ($$$$;$) { | Line 523 sub parse_byte_stream ($$$$;$) { |
| 523 | ## Step 1 | ## Step 1 |
| 524 | if ($charset->{category} & | if ($charset->{category} & |
| 525 | Message::Charset::Info::CHARSET_CATEGORY_UTF16 ()) { | Message::Charset::Info::CHARSET_CATEGORY_UTF16 ()) { |
| 526 | $charset = Message::Charset::Info->get_by_iana_name ('utf-8'); | $charset = Message::Charset::Info->get_by_html_name ('utf-8'); |
| 527 | ($char_stream, $e_status) = $charset->get_decode_handle | ($char_stream, $e_status) = $charset->get_decode_handle |
| 528 | ($byte_stream, | ($byte_stream, |
| 529 | byte_buffer => \ $buffer->{buffer}); | byte_buffer => \ $buffer->{buffer}); |
| # | Line 493 sub parse_byte_stream ($$$$;$) { | Line 533 sub parse_byte_stream ($$$$;$) { |
| 533 | ## Step 2 | ## Step 2 |
| 534 | if (defined $self->{input_encoding} and | if (defined $self->{input_encoding} and |
| 535 | $self->{input_encoding} eq $charset_name) { | $self->{input_encoding} eq $charset_name) { |
| 536 | !!!parse-error (type => 'charset label:matching', ## TODO: type | !!!parse-error (type => 'charset label:matching', |
| 537 | value => $charset_name, | text => $charset_name, |
| 538 | level => $self->{info_level}); | level => $self->{level}->{info}); |
| 539 | $self->{confident} = 1; | $self->{confident} = 1; |
| 540 | return; | return; |
| 541 | } | } |
| 542 | ||
| 543 | !!!parse-error (type => 'charset label detected:'.$self->{input_encoding}. | !!!parse-error (type => 'charset label detected', |
| 544 | ':'.$charset_name, level => 'w', token => $token); | text => $self->{input_encoding}, |
| 545 | value => $charset_name, | |
| 546 | level => $self->{level}->{warn}, | |
| 547 | token => $token); | |
| 548 | ||
| 549 | ## Step 3 | ## Step 3 |
| 550 | # if (can) { | # if (can) { |
| # | Line 517 sub parse_byte_stream ($$$$;$) { | Line 560 sub parse_byte_stream ($$$$;$) { |
| 560 | ||
| 561 | my $char_onerror = sub { | my $char_onerror = sub { |
| 562 | my (undef, $type, %opt) = @_; | my (undef, $type, %opt) = @_; |
| 563 | !!!parse-error (%opt, type => $type, | !!!parse-error (layer => 'encode', |
| 564 | %opt, type => $type, | |
| 565 | line => $self->{line}, column => $self->{column} + 1); | line => $self->{line}, column => $self->{column} + 1); |
| 566 | if ($opt{octets}) { | if ($opt{octets}) { |
| 567 | ${$opt{octets}} = "\x{FFFD}"; # relacement character | ${$opt{octets}} = "\x{FFFD}"; # relacement character |
| 568 | } | } |
| 569 | }; | }; |
| 570 | $char_stream->onerror ($char_onerror); | |
| 571 | my $wrapped_char_stream = $get_wrapper->($char_stream); | |
| 572 | $wrapped_char_stream->onerror ($char_onerror); | |
| 573 | ||
| 574 | my @args = @_; shift @args; # $s | my @args = @_; shift @args; # $s |
| 575 | my $return; | my $return; |
| 576 | try { | try { |
| 577 | $return = $self->parse_char_stream ($char_stream, @args); | $return = $self->parse_char_stream ($wrapped_char_stream, @args); |
| 578 | } catch Whatpm::HTML::RestartParser with { | } catch Whatpm::HTML::RestartParser with { |
| 579 | ## NOTE: Invoked after {change_encoding}. | ## NOTE: Invoked after {change_encoding}. |
| 580 | ||
| $self->{input_encoding} = $charset->get_iana_name; | ||
| 581 | if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) { | if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) { |
| 582 | !!!parse-error (type => 'chardecode:fallback', ## TODO: type name | $self->{input_encoding} = $charset->get_iana_name; ## TODO: Should we set actual charset decoder's encoding name? |
| 583 | value => $self->{input_encoding}, | !!!parse-error (type => 'chardecode:fallback', |
| 584 | level => $self->{unsupported_level}, | level => $self->{level}->{uncertain}, |
| 585 | line => 1, column => 1); | #text => $self->{input_encoding}, |
| 586 | line => 1, column => 1, | |
| 587 | layer => 'encode'); | |
| 588 | } elsif (not ($e_status & | } elsif (not ($e_status & |
| 589 | Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) { | Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) { |
| 590 | !!!parse-error (type => 'chardecode:no error', ## TODO: type name | $self->{input_encoding} = $charset->get_iana_name; |
| 591 | value => $self->{input_encoding}, | !!!parse-error (type => 'chardecode:no error', |
| 592 | level => $self->{unsupported_level}, | text => $self->{input_encoding}, |
| 593 | line => 1, column => 1); | level => $self->{level}->{uncertain}, |
| 594 | line => 1, column => 1, | |
| 595 | layer => 'encode'); | |
| 596 | } else { | |
| 597 | $self->{input_encoding} = $charset->get_iana_name; | |
| 598 | } | } |
| 599 | $self->{confident} = 1; | $self->{confident} = 1; |
| 600 | $char_stream->onerror ($char_onerror); | |
| 601 | $return = $self->parse_char_stream ($char_stream, @args); | $wrapped_char_stream = $get_wrapper->($char_stream); |
| 602 | $wrapped_char_stream->onerror ($char_onerror); | |
| 603 | ||
| 604 | $return = $self->parse_char_stream ($wrapped_char_stream, @args); | |
| 605 | }; | }; |
| 606 | return $return; | return $return; |
| 607 | } # parse_byte_stream | } # parse_byte_stream |
| # | Line 561 sub parse_byte_stream ($$$$;$) { | Line 615 sub parse_byte_stream ($$$$;$) { |
| 615 | ## such as |parse_byte_string| in this module, must ensure that it does | ## such as |parse_byte_string| in this module, must ensure that it does |
| 616 | ## strip the BOM and never strip any ZWNBSP. | ## strip the BOM and never strip any ZWNBSP. |
| 617 | ||
| 618 | sub parse_char_string ($$$;$) { | sub parse_char_string ($$$;$$) { |
| 619 | #my ($self, $s, $doc, $onerror, $get_wrapper) = @_; | |
| 620 | my $self = shift; | my $self = shift; |
| require utf8; | ||
| 621 | my $s = ref $_[0] ? $_[0] : \($_[0]); | my $s = ref $_[0] ? $_[0] : \($_[0]); |
| 622 | open my $input, '<' . (utf8::is_utf8 ($$s) ? ':utf8' : ''), $s; | require Whatpm::Charset::DecodeHandle; |
| 623 | my $input = Whatpm::Charset::DecodeHandle::CharString->new ($s); | |
| 624 | if ($_[3]) { | |
| 625 | $input = $_[3]->($input); | |
| 626 | } | |
| 627 | return $self->parse_char_stream ($input, @_[1..$#_]); | return $self->parse_char_stream ($input, @_[1..$#_]); |
| 628 | } # parse_char_string | } # parse_char_string |
| 629 | *parse_string = \&parse_char_string; | *parse_string = \&parse_char_string; ## NOTE: Alias for backward compatibility. |
| 630 | ||
| 631 | sub parse_char_stream ($$$;$) { | sub parse_char_stream ($$$;$) { |
| 632 | my $self = ref $_[0] ? shift : shift->new; | my $self = ref $_[0] ? shift : shift->new; |
| # | Line 611 sub parse_char_stream ($$$;$) { | Line 669 sub parse_char_stream ($$$;$) { |
| 669 | $self->{column} = 0; | $self->{column} = 0; |
| 670 | } elsif ($self->{next_char} == 0x000D) { # CR | } elsif ($self->{next_char} == 0x000D) { # CR |
| 671 | !!!cp ('j2'); | !!!cp ('j2'); |
| 672 | ## TODO: support for abort/streaming | |
| 673 | my $next = $input->getc; | my $next = $input->getc; |
| 674 | if (defined $next and $next ne "\x0A") { | if (defined $next and $next ne "\x0A") { |
| 675 | $self->{next_next_char} = $next; | $self->{next_next_char} = $next; |
| # | Line 630 sub parse_char_stream ($$$;$) { | Line 689 sub parse_char_stream ($$$;$) { |
| 689 | (0x007F <= $self->{next_char} and $self->{next_char} <= 0x009F) or | (0x007F <= $self->{next_char} and $self->{next_char} <= 0x009F) or |
| 690 | (0xD800 <= $self->{next_char} and $self->{next_char} <= 0xDFFF) or | (0xD800 <= $self->{next_char} and $self->{next_char} <= 0xDFFF) or |
| 691 | (0xFDD0 <= $self->{next_char} and $self->{next_char} <= 0xFDDF) or | (0xFDD0 <= $self->{next_char} and $self->{next_char} <= 0xFDDF) or |
| 692 | ## ISSUE: U+FDE0-U+FDEF are not excluded | |
| 693 | { | { |
| 694 | 0xFFFE => 1, 0xFFFF => 1, 0x1FFFE => 1, 0x1FFFF => 1, | 0xFFFE => 1, 0xFFFF => 1, 0x1FFFE => 1, 0x1FFFF => 1, |
| 695 | 0x2FFFE => 1, 0x2FFFF => 1, 0x3FFFE => 1, 0x3FFFF => 1, | 0x2FFFE => 1, 0x2FFFF => 1, 0x3FFFE => 1, 0x3FFFF => 1, |
| # | Line 642 sub parse_char_stream ($$$;$) { | Line 702 sub parse_char_stream ($$$;$) { |
| 702 | 0x10FFFE => 1, 0x10FFFF => 1, | 0x10FFFE => 1, 0x10FFFF => 1, |
| 703 | }->{$self->{next_char}}) { | }->{$self->{next_char}}) { |
| 704 | !!!cp ('j5'); | !!!cp ('j5'); |
| 705 | !!!parse-error (type => 'control char', level => $self->{must_level}); | if ($self->{next_char} < 0x10000) { |
| 706 | ## TODO: error type documentation | !!!parse-error (type => 'control char', |
| 707 | text => (sprintf 'U+%04X', $self->{next_char})); | |
| 708 | } else { | |
| 709 | !!!parse-error (type => 'control char', | |
| 710 | text => (sprintf 'U-%08X', $self->{next_char})); | |
| 711 | } | |
| 712 | } | } |
| 713 | }; | }; |
| 714 | $self->{prev_char} = [-1, -1, -1]; | $self->{prev_char} = [-1, -1, -1]; |
| 715 | $self->{next_char} = -1; | $self->{next_char} = -1; |
| 716 | ||
| 717 | $self->{read_until} = sub { | |
| 718 | #my ($scalar, $specials_range, $offset) = @_; | |
| 719 | my $specials_range = $_[1]; | |
| 720 | return 0 if defined $self->{next_next_char}; | |
| 721 | my $count = $input->manakai_read_until | |
| 722 | ($_[0], | |
| 723 | qr/(?![$specials_range\x{FDD0}-\x{FDDF}\x{FFFE}\x{FFFF}\x{1FFFE}\x{1FFFF}\x{2FFFE}\x{2FFFF}\x{3FFFE}\x{3FFFF}\x{4FFFE}\x{4FFFF}\x{5FFFE}\x{5FFFF}\x{6FFFE}\x{6FFFF}\x{7FFFE}\x{7FFFF}\x{8FFFE}\x{8FFFF}\x{9FFFE}\x{9FFFF}\x{AFFFE}\x{AFFFF}\x{BFFFE}\x{BFFFF}\x{CFFFE}\x{CFFFF}\x{DFFFE}\x{DFFFF}\x{EFFFE}\x{EFFFF}\x{FFFFE}\x{FFFFF}])[\x20-\x7E\xA0-\x{D7FF}\x{E000}-\x{10FFFD}]/, | |
| 724 | $_[2]); | |
| 725 | if ($count) { | |
| 726 | $self->{column} += $count; | |
| 727 | $self->{column_prev} += $count; | |
| 728 | $self->{prev_char} = [-1, -1, -1]; | |
| 729 | $self->{next_char} = -1; | |
| 730 | } | |
| 731 | return $count; | |
| 732 | }; # $self->{read_until} | |
| 733 | ||
| 734 | my $onerror = $_[2] || sub { | my $onerror = $_[2] || sub { |
| 735 | my (%opt) = @_; | my (%opt) = @_; |
| 736 | my $line = $opt{token} ? $opt{token}->{line} : $opt{line}; | &nb |