Changeset 21797 for src/perl6

Show
Ignore:
Timestamp:
08/06/08 03:47:11 (4 months ago)
Author:
lwall
Message:

[STD] much improved error messages on runaway strings and other "worries"

Location:
src/perl6
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • src/perl6/Cursor.pmc

    r21789 r21797  
    1414$::HIGHMESS = ''; 
    1515$::HIGHEXPECT = {}; 
     16$::COMPILING::LAST_NIBBLE = { firstline => 0, lastline => 0 }; 
     17$::COMPILING::LAST_NIBBLE_MULTILINE = { firstline => 0, lastline => 0 }; 
    1618$::COMPILING::LINE = 1; 
    1719$::COMPILING::FILE = '(eval)'; 
     
    5961sub deb { my $self = shift; 
    6062    my $pos = ref $self && defined $self->{_pos} ? $self->{_pos} : "?"; 
    61     print ::LOG $pos,'/',$::COMPILING::LINE, "\t", $CTX, ' ', @_, "\n"; 
     63    print ::LOG $pos,'/',$self->lineof($pos), "\t", $CTX, ' ', @_, "\n"; 
    6264} 
    6365 
  • src/perl6/STD.pm

    r21792 r21797  
    394394token vws { 
    395395    \v :: 
    396     { $COMPILING::LINE++ } 
     396    { $COMPILING::LINE++ } # XXX wrong several ways 
    397397    [ '#DEBUG -1' { say "DEBUG"; $STD::DEBUG = $*DEBUG = -1; } ]? 
    398398} 
     
    15801580        | d \d+               [ _ \d+]* 
    15811581        | \d+[_\d+]* 
    1582 #            {{ START { $¢.worry("Leading 0 does not indicate octal in Perl 6") } }} 
     1582            { $¢.worry("Leading 0 does not indicate octal in Perl 6") } 
    15831583        ] 
    15841584    | \d+[_\d+]* 
     
    17991799    :my @nibbles = (); 
    18001800    :my $buf = self.orig; 
     1801    :my $multiline = 0; 
     1802    { $<firstpos> = self.pos; } 
    18011803    [ 
    18021804        [ 
     
    18151817                        } 
    18161818        |            :: . 
    1817                         { 
    1818                             $text ~= substr($$buf, $¢.pos-1, 1); 
    1819                         } 
     1819                        {{ 
     1820                            my $ch = substr($$buf, $¢.pos-1, 1); 
     1821                            $text ~= $ch; 
     1822                            if $ch ~~ "\n" { 
     1823                                $multiline++; 
     1824                                $COMPILING::LINE++; # bypasses <vws> 
     1825                            } 
     1826                        }} 
    18201827        ] 
    18211828    ]* 
    1822     { push @nibbles, $text; $<nibbles> = [@nibbles]; } 
     1829    { 
     1830        push @nibbles, $text; $<nibbles> = [@nibbles]; 
     1831        $<lastpos> = $¢.pos; 
     1832        $COMPILING::LAST_NIBBLE = $¢; 
     1833        $COMPILING::LAST_NIBBLE_MULTILINE = $¢ if $multiline; 
     1834    } 
    18231835} 
    18241836 
     
    18321844 
    18331845token quote:sym</ />   { 
    1834     '/' <nibble( $¢.cursor_fresh( ::Regex ).unbalanced("/") )> '/' 
    1835     [ (< i g s m x c e ] >+)  
    1836         {{ 
    1837             given $0 { 
    1838                 /i/ and $¢.obs('/i',':i'); 
    1839                 /g/ and $¢.obs('/g',':g'); 
    1840                 /s/ and $¢.obs('/s','^^ and $$ anchors'); 
    1841                 /m/ and $¢.obs('/m','. or \N'); 
    1842                 /x/ and $¢.obs('/x','normal default whitespace'); 
    1843                 /c/ and $¢.obs('/c',':c or :p'); 
    1844                 /e/ and $¢.obs('/e','interpolated {...} or s{} = ... form'); 
    1845                 $¢.obs('suffix regex modifiers','prefix adverbs'); 
    1846             } 
    1847         }} 
    1848     ]? 
     1846    '/' <nibble( $¢.cursor_fresh( ::Regex ).unbalanced("/") )> [ '/' || <.panic: "Unable to parse regex; couldn't find final '/'"> ] 
     1847    <old_rx_mods>? 
    18491848} 
    18501849 
     
    18871886token quote_mod:b  { <sym> } 
    18881887 
    1889 token quote:rx { <sym> » <!before '('> <quibble( $¢.cursor_fresh( ::Regex ) )> } 
    1890  
    1891 token quote:m  { <sym> » <!before '('> <quibble( $¢.cursor_fresh( ::Regex ) )> } 
    1892 token quote:mm { <sym> » <!before '('> <quibble( $¢.cursor_fresh( ::Regex ).tweak(:s))> } 
     1888token quote:rx { 
     1889    <sym> » <!before '('> 
     1890    <quibble( $¢.cursor_fresh( ::Regex ) )> 
     1891    <old_rx_mods>? 
     1892} 
     1893 
     1894token quote:m  { 
     1895    <sym> » <!before '('> 
     1896    <quibble( $¢.cursor_fresh( ::Regex ) )> 
     1897    <old_rx_mods>? 
     1898} 
     1899 
     1900token quote:mm { 
     1901    <sym> » <!before '('> 
     1902    <quibble( $¢.cursor_fresh( ::Regex ).tweak(:s))> 
     1903    <old_rx_mods>? 
     1904} 
    18931905 
    18941906token quote:s { 
    1895     <sym> » <!before '('> <pat=sibble( $¢.cursor_fresh( ::Regex ), $¢.cursor_fresh( ::STD::Q ).tweak(:qq))> 
    1896 } 
     1907    <sym> » <!before '('> 
     1908    <pat=sibble( $¢.cursor_fresh( ::Regex ), $¢.cursor_fresh( ::STD::Q ).tweak(:qq))> 
     1909    <old_rx_mods>? 
     1910} 
     1911 
    18971912token quote:ss { 
    1898     <sym> » <!before '('> <pat=sibble( $¢.cursor_fresh( ::Regex ).tweak(:s), $¢.cursor_fresh( ::STD::Q ).tweak(:qq))> 
     1913    <sym> » <!before '('> 
     1914    <pat=sibble( $¢.cursor_fresh( ::Regex ).tweak(:s), $¢.cursor_fresh( ::STD::Q ).tweak(:qq))> 
     1915    <old_rx_mods>? 
    18991916} 
    19001917token quote:tr { 
    19011918    <sym> » <!before '('> <pat=tribble( $¢.cursor_fresh( ::STD::Q ).tweak(:q))> 
    1902 } 
     1919    <old_tr_mods>? 
     1920} 
     1921 
     1922token old_rx_mods { 
     1923    (< i g s m x c e ] >+)  
     1924    {{ 
     1925        given $0.text { 
     1926            $_ ~~ /i/ and $¢.worryobs('/i',':i'); 
     1927            $_ ~~ /g/ and $¢.worryobs('/g',':g'); 
     1928            $_ ~~ /s/ and $¢.worryobs('/s','^^ and $$ anchors'); 
     1929            $_ ~~ /m/ and $¢.worryobs('/m','. or \N'); 
     1930            $_ ~~ /x/ and $¢.worryobs('/x','normal default whitespace'); 
     1931            $_ ~~ /c/ and $¢.worryobs('/c',':c or :p'); 
     1932            $_ ~~ /e/ and $¢.worryobs('/e','interpolated {...} or s{} = ... form'); 
     1933            $¢.obs('suffix regex modifiers','prefix adverbs'); 
     1934        } 
     1935    }} 
     1936} 
     1937 
     1938token old_tr_mods { 
     1939    (< c d s ] >+)  
     1940    {{ 
     1941        given $0.text { 
     1942            $_ ~~ /c/ and $¢.worryobs('/c',':c'); 
     1943            $_ ~~ /d/ and $¢.worryobs('/g',':d'); 
     1944            $_ ~~ /s/ and $¢.worryobs('/s',':s'); 
     1945            $¢.obs('suffix transliteration modifiers','prefix adverbs'); 
     1946        } 
     1947    }} 
     1948} 
     1949 
    19031950 
    19041951token quote:quasi { 
     
    29372984    { <sym> } 
    29382985 
    2939 # XXX need to do something to turn subcall into method call here... 
    2940 token infix:sym<.=> ( --> Item_assignment) 
    2941     { <sym> <.ws> { $<O><nextterm> = 'dottyop' } } 
     2986token infix:sym<.=> ( --> Item_assignment) { 
     2987    <sym> <.ws> 
     2988    [ <?before \w+';' | < new sort subst trans > > || <worryobs('.= as append operator', '~=')> ] 
     2989    { $<O><nextterm> = 'dottyop' } 
     2990} 
    29422991 
    29432992token infix:sym« => » ( --> Item_assignment) 
     
    37143763# token panic (Str $s) { <commit> <fail($s)> } 
    37153764 
     3765method panic (Str $s) { 
     3766    my $m = "############# PARSE FAILED #############"; 
     3767    my $here = self; 
     3768 
     3769    # Have we backed off recently? 
     3770    my $highvalid = self.pos <= $*HIGHWATER; 
     3771 
     3772    $here = self.cursor($*HIGHWATER) if $highvalid; 
     3773 
     3774    my $first = $here.lineof($COMPILING::LAST_NIBBLE.<firstpos>); 
     3775    my $last = $here.lineof($COMPILING::LAST_NIBBLE.<lastpos>); 
     3776    if $here.lineof($here.pos) == $last and $first != $last { 
     3777        $m ~= "\n(Possible runaway string from line $first)"; 
     3778    } 
     3779    else { 
     3780        $first = $here.lineof($COMPILING::LAST_NIBBLE_MULTILINE.<firstpos>); 
     3781        $last = $here.lineof($COMPILING::LAST_NIBBLE_MULTILINE.<lastpos>); 
     3782        # the bigger the string (in lines), the further back we suspect it 
     3783        if $here.lineof($here.pos) - $last < $last - $first  { 
     3784            $m ~= "\n(Possible runaway string from line $first to line $last)"; 
     3785        } 
     3786    } 
     3787 
     3788    $m ~= "\n" ~ $s; 
     3789 
     3790    if $highvalid { 
     3791        $m ~= $*HIGHMESS if $*HIGHMESS; 
     3792    } 
     3793    else { 
     3794        # not in backoff, so at "bleeding edge", as it were... therefore probably 
     3795        # the exception will be caught and re-panicked later, so remember message 
     3796        $*HIGHMESS ~= "\n" ~ $s; 
     3797    } 
     3798 
     3799    $m ~= $here.locmess; 
     3800 
     3801    if $highvalid and %$*HIGHEXPECT { 
     3802        my @keys = sort keys %$*HIGHEXPECT; 
     3803        if @keys > 1 { 
     3804            $m ~= "\n    expecting any of:\n\t" ~ join("\n\t", sort keys %$*HIGHEXPECT); 
     3805        } 
     3806        else { 
     3807            $m ~= "\n    expecting @keys"; 
     3808        } 
     3809    } 
     3810 
     3811    if @COMPILING::WORRIES { 
     3812        $m ~= "\nOther potential difficulties:\n  " ~ join( "\n  ", @COMPILING::WORRIES); 
     3813    } 
     3814 
     3815    die $m ~ "\n"; 
     3816} 
     3817 
     3818method worry (Str $s) { 
     3819    push @COMPILING::WORRIES, $s ~ self.locmess; 
     3820} 
     3821 
    37163822method locmess () { 
    37173823    my $orig = self.orig; 
    37183824    my $text = $$orig; 
    37193825    my $pre = substr($text, 0, self.pos); 
    3720     my $line = 1 + $pre ~~ tr!\n!\n!; 
     3826    my $line = self.lineof(self.pos); 
    37213827    $pre = substr($pre, -40, 40); 
    37223828    1 while $pre ~~ s!.*\n!!; 
     
    37243830    1 while $post ~~ s!(\n.*)!!; 
    37253831    " at " ~ $COMPILING::FILE ~ " line $line:\n------> " ~ $Cursor::GREEN ~ $pre ~ $Cursor::RED ~  
    3726         "$post$Cursor::CLEAR\n"; 
    3727 } 
    3728  
    3729 method panic (Str $s) { 
    3730     my $m = "############# PARSE FAILED #############\n$s"; 
    3731     if self.pos <= $*HIGHWATER and %$*HIGHEXPECT { 
    3732         $m ~= "\n" ~ $*HIGHMESS if $*HIGHMESS; 
    3733         $m ~= self.cursor($*HIGHWATER).locmess; 
    3734         my @keys = sort keys %$*HIGHEXPECT; 
    3735         if @keys > 1 { 
    3736             $m ~= "    expecting any of:\n\t" ~ join("\n\t", sort keys %$*HIGHEXPECT) ~ "\n"; 
    3737         } 
    3738         else { 
    3739             $m ~= "    expecting @keys\n"; 
    3740         } 
    3741     } 
    3742     else { 
    3743         $*HIGHMESS = $s; 
    3744         $m ~= self.locmess; 
    3745     } 
    3746     die $m; 
    3747 } 
    3748  
    3749 method worry (Str $s) { 
    3750     warn $s ~ self.locmess; 
     3832        "$post$Cursor::CLEAR"; 
     3833} 
     3834 
     3835method lineof ($p) { 
     3836    return 1 unless defined $p; 
     3837    my $posprops = self.<_>; 
     3838    my $line = $posprops.[$p]<line>; 
     3839    return $line if $line; 
     3840    $line = 1; 
     3841    my $pos = 0; 
     3842    my $orig = self.orig; 
     3843    my $text = $$orig; 
     3844    while $text ne '' { 
     3845        $posprops.[$pos++]<line> = $line; 
     3846        $line++ if substr($text,0,1,'') eq "\n"; 
     3847    } 
     3848    return $posprops.[$p]<line> // 0; 
    37513849} 
    37523850 
     
    37623860} 
    37633861 
     3862method worryobs (Str $old, Str $new, Str $when = ' in Perl 6') { 
     3863    self.worry("Possible obsolete use of $old;$when please use $new instead"); 
     3864    self; 
     3865} 
     3866 
    37643867## vim: expandtab sw=4 syntax=perl6