装配说明的正则表达式

时间:2011-04-16 18:41:37

标签: c++ regex boost

我正在为虚构的汇编语言编写自己的解析器。这些说明与任何正常的汇编指令非常相似:

[INSTRUCTION] [OP]*

其中op可以是0-3个操作数。我希望能够使用与此匹配的表达式。这是用C ++编写的boost :: regex。我自己是一个正则表达式noobie,试图理解每个符号的提升文档。

现在,我已经有一个表达式可以匹配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]+))*

这看起来非常绿色,可怜的正则表达式。它也无法正常工作。我正在考虑使用递归表达式,但是我查看了文档,我不妨在我的额头上涂抹“矫枉过正”。

我意识到我可以格式化该行以取出所有逗号,但我希望能够首先编写和理解regexp表达式,然后以简单的方式执行。任何帮助将不胜感激。

5 个答案:

答案 0 :(得分:4)

字符串如:

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 :(得分:1)

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

答案 2 :(得分:1)

有一个野牛语法作为HLA汇编程序源的一部分,你可以在这里找到

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

我建议使用正确的语法:)

答案 3 :(得分:1)

如果您认真对待这一点,则必须考虑每一行,所有边界条件,错误等。仅仅匹配一个证书形式,而不了解其他形式的任何内容。

如果使用正则表达式,更简洁的方法是保留可以分析的固定数量的缓冲区。对于基本的第一级语法检查程序,这是相当复杂的。

这是一个开始:

/
  ^
     (?!\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 ) { }

答案 4 :(得分:0)

你试试这个:

^[\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_] ))?)?)?

可以匹配label,OP,params