Регулярное выражение для инструкций по сборке - PullRequest
0 голосов
/ 16 апреля 2011

Я сейчас пишу свой собственный парсер для вымышленного ассемблера.Инструкции очень похожи на любую обычную инструкцию по сборке:

[INSTRUCTION] [OP]*

, где op может быть 0-3 операнда.Я хочу иметь возможность использовать выражение, которое соответствует этому.Это пишется на C ++ с boost :: regex.Я сам являюсь новичком в области регулярных выражений и пытаюсь понять документацию поддержки того, что делает каждый символ.

Теперь у меня уже есть выражение, которое может соответствовать 0-3 операндам, например:

Sample Instructions:
    MOVI 8 10
    ADDI 8 8 10
    NOP
    BNEZI -1

Expression: ^([a-z]+)( ([-,0-9]+))*

Тем не менее, я не могу создать подходящее выражение, которое обрабатывает те же инструкции, разделенные запятыми:

Sample Instructions:
    MOVI 8, 10
    ADDI 8, 8, 10

Это действительно сбивает меня с толку.Я пытался переписать свое выражение так:

^([a-z]+)( ([-,0-9]+))*(, ([-,0-9]+))*

Это выглядит очень зелёным, плохое регулярное выражение.Это также не работает правильно.Я думал об использовании рекурсивного выражения, но я посмотрел на документацию, и с тем же успехом мог бы набросать «излишне» на лбу.

Я понимаю, что мог бы просто отформатировать строку, чтобы убрать все запятые, но я бы предпочел сначала написать и понять выражение регулярного выражения, а затем сделать это простым способом.Любая помощь будет оценена.

Ответы [ 5 ]

4 голосов
/ 16 апреля 2011

Строка типа:

ADDI 8, 8, 10

может быть сопоставлена ​​с помощью регулярного выражения:

[a-zA-Z]+[ \t]+-?[0-9]+([ \t]*,[ \t]*-?[0-9]+)*

Краткое объяснение:

[a-zA-Z]+   # match an instruction
[ \t]+      # match one or more spaces or tabs
-?[0-9]+    # match an integer value with an option minus sign in front of it
(           # open group 1
  [ \t]*    #   match zero or more spaces or tabs
  ,         #   match a comma
  [ \t]*    #   match zero or more spaces or tabs
  -?[0-9]+  #   match an integer value with an option minus sign in front of it
)*          # close group 1, and repeat it zero or more times

ИмеяСказав все это, я должен согласиться с комментарием dmckee: правильный парсер - это путь, даже если это просто вымышленный язык, который вы анализируете.

1 голос
/ 17 апреля 2011

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

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

Это начало:

/
  ^
     (?!\s*$)
     \s* 
     (?|
         ([a-zA-Z]+)
         \s*
         ((?<=\s)
          -?\d+|) (?!,\s*$) (?:,\s*|\s*$)  
         (-?\d+|) (?!,\s*$) (?:,\s*|\s*$)
         (-?\d+|) \s*$
         ()
       |
         ()()()()(.+)
     )
  $
/x;

Тестовый пример Perl с использованием строк с разделителями новой строки:

use strict;
use warnings;

my $rx = qr/
  ^
     (?!\s*$)
     \s* 
     (?|
         ([a-zA-Z]+)
         \s*
         ((?<=\s)
          -?\d+|) (?!,\s*$) (?:,\s*|\s*$)  
         (-?\d+|) (?!,\s*$) (?:,\s*|\s*$)
         (-?\d+|) \s*$
         ()
       |
         ()()()()(.+)
     )
  $/x;

my $cnt = 0;  # line counter

while ( my $line = <DATA> )
{
    ++$cnt;

    if ( $line =~ /$rx/ )
    {
        if (length $5) {
           print "\nSyntax error ? (line $cnt)   '$5'\n";
        }
        else {
           print "\nInstruction:  '$1'\n";
           print "     op1 = '$2'\n";
           print "     op2 = '$3'\n";
           print "     op3 = '$4'\n";
        }
    }
}

__DATA__

    MOVI 8 10
    ADDI 8 8 10

    NOP
    BNEZI -1
    InstA  0
    InstB  1,
    InstC  2,3, 4
    InstD  5,6, 7, 8

    MOVI 7, 8
    ADDI 9, 10, 11
    ADDI 12, 13 14

Вывод:

Syntax error ? (line 2)   'MOVI 8 10'

Syntax error ? (line 3)   'ADDI 8 8 10'

Instruction:  'NOP'
     op1 = ''
     op2 = ''
     op3 = ''

Instruction:  'BNEZI'
     op1 = '-1'
     op2 = ''
     op3 = ''

Instruction:  'InstA'
     op1 = '0'
     op2 = ''
     op3 = ''

Syntax error ? (line 8)   'InstB  1,'

Instruction:  'InstC'
     op1 = '2'
     op2 = '3'
     op3 = '4'

Syntax error ? (line 10)   'InstD  5,6, 7, 8'

Instruction:  'MOVI'
     op1 = '7'
     op2 = '8'
     op3 = ''

Instruction:  'ADDI'
     op1 = '9'
     op2 = '10'
     op3 = '11'

Syntax error ? (line 14)   'ADDI 12, 13 14'

Альтернативно, все данные в строке (то же регулярное выражение).

while ( $str =~ /$rx/mg ) { }

1 голос
/ 16 апреля 2011

Существует грамматика бизонов как часть источника ассемблера HLA, которую вы можете получить здесь

http://webster.cs.ucr.edu/AsmTools/HLA/frozen.html

Я предлагаю использовать правильную грамматику:)

1 голос
/ 16 апреля 2011

попробуй

^([a-z]+)( ([-,0-9]+)((,|\s)[-,0-9]+)*)*
0 голосов
/ 04 апреля 2017

Вы можете попробовать это:

^[\t ]*(?:([.A-Za-z0-9_] )[:])?(?:[\t ]*([A-Za-z]{2,4})(?:[\t ] (\[([A-Za-z0-9_] (([- ])[0-9] )?)\]|\". ?\"|\'. ?\'|[.A-Za-z0-9_] )(?:[\t ]*[,][\t ]*(\[([A-Za-z0-9_] (([- ])[0-9] )?)\]|\". ?\"|\'. ?\'|[.A-Za-z0-9_] ))?)?)?

может соответствовать метке, OP, params

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...