我正在为虚构的汇编语言编写自己的解析器。这些说明与任何正常的汇编指令非常相似:
[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表达式,然后以简单的方式执行。任何帮助将不胜感激。
答案 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)
答案 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