2014-10-05 2 views
2

В моей программе, я храню уровень отступа видел в @indentation_stackСравнивая с и т

Например:

$line =~ /^(\s*)(if|elif|else|while)/ 
push(@indentation_stack, $1); 

Я тогда сравнить уровень отступа я вижу в следующей строке уровень отступа в последнем элементе @indentation_stack.

if ($line =~ /^(\s*)[^\s+]/) { 
    while (@indentation_stack && $1 le $indentation_stack[-1]){   
      print $indentation_stack[-1],"}\n";   
      pop @indentation_stack;   
    } 
} 

Идея, если отступы на последующую строке эквивалентны последний элемент @indentation_stack, я напечатать } и символ новой строки.

Это работает нормально, пока отступы состоят из spaces. Однако, если я создаю тот же уровень отступов, используя \t, мой код не работает должным образом.

EDIT: Если все интервалы согласованы, то используются все \t или все spaces, тогда проблем нет. Поэтому я думаю, что я пытаюсь понять, как я могу просто сравнить пространство. То есть \t может быть эквивалентно числу spaces.

Кто-нибудь знает, почему это происходит?

Благодарим за помощь.

+1

Большинство языков, чувствительных к отступам, просто запрещают файлы, которые смешивают вкладки и пробелы. Они не сопоставимы, по крайней мере, не так, чтобы все были счастливы. – hobbs

ответ

3

Проблема с вкладками в сравнении с пространством является старой, без ответа, выбрать один и быть последовательным, так как смешивание двух является плохим. Различные редакторы могут отображать вкладки как разные числа пробелов и даже динамически в пределах одного файла относительно их контекста.

Таким образом, множество редакторов, emacs - это то, о чем я знаю, предлагают способы автоматического преобразования вкладок в пробелы для вас и только вставки пробелов при нажатии на вкладку.

Кроме того, ваша программа может принимать вкладки, чтобы быть определенным количеством пробелов, хотя для этого, вероятно, потребуется преобразование вкладок в пробелы по всем строкам, а не только из тех, которые вы создаете. Если вы не хотите делать какое-то смешанное представление или конвертировать в ближайший промежуток между вкладками - это сложная задача для небольшой причины.

+0

+1, но вы можете упомянуть, как вы ** можете совместить пробел (буквальный пробел, шестнадцатеричный escape и т. Д.). –

+0

Черт возьми, Питер. Я хотел использовать 'space' вместо' \ s' в моем вопросе. –

+0

@Giri Я отказался от этого абзаца от ответа, чтобы продолжить inline с вопросом –

1

Вы спрашиваете, как рассчитать видимую длину вкладок? Вкладки переместите курсор к следующей вкладке.

use constant TAB_STOP => 4; 

sub indent_size { 
    my ($s) = @_; 
    my $i = 0; 
    while ($s =~ /\G([ \t])/g) { 
     $i += $1 eq "\t" ? (TAB_STOP - ($i % TAB_STOP)) : 1; 
    } 

    return $i; 
} 

if (my ($indent) = $line =~ /^([ \t]+)[^ \t\n]/) { 
    my $indent_size = indent_size($indent); 
    while (@indent_stack && $indent_size <= indent_size($indent_stack[-1])) { 
     print pop(@indent_stack), "}\n";   
    } 
} 

Было бы более эффективно хранить отступ и его длину в стеке.

+0

Спасибо @ikegami. Я должен был быть более ясным в своем вопросе. Я хотел знать, был ли простой способ сравнить уровень отступов в строке, независимо от того, состоял ли он из 'пробелов' или' tabs'. В соответствии с ответом @Peter R ниже, без преобразования всех «вкладок» в «пробелы», возможно, нет. –

+0

Итак, вы хотите рассчитать видимую длину вкладок. Вам не нужно их конвертировать. как показано в моем обновлении. – ikegami

Смежные вопросы