我正在尝试编写一个在bash脚本中使用的正则表达式模式,该脚本检查switch
语句(C ++)的语法。
我想要遵循的switch
语句的语法如下:
switch(expression)
{
case constant-expression:
statement(s);
break; // must be present
case constant-expression:
statement(s);
break; // must be present
....
....
default : // must be present
statement(s);
break; // must be present
}
请注意,即使break
和default
声明不是必须的,我也希望检查它们的存在。
我写了这个正则表达式模式来匹配开关块。
switch(.*?)\n(\s)*?{(\n(.*?))*?(\n(\s)*case(.*?):?(\n(.*?))*?break;)+(\n(.*?))*?\n(\s)*(default:)?(\n(\s)*)*(break|return(.*?))?;(\n(\s)*(.*?))*}
它成功匹配了切换块,但问题是它匹配switch
块,即使缺少break和default语句。我尝试将+
运算符与break
和default
字词一起使用,但它们似乎无效。
编辑更新:
是否可以使用解析器匹配开关块,例如以下开关块?
switch (PC_INT[address.port][address.pin])
{
#if defined (__AVR_ATmega2560__) || defined(__AVR_AT90CAN128__)
case EINT_0:
// Mask the interrupt so it doesn't fire anymore, i.e put a zero in the mask register.
EIMSK &= ~(1 << INT0);
break;
case EINT_1:
EIMSK &= ~(1 << INT1);
break;
....
default:
return GPIO_INT_OUT_OF_RANGE;
#elif defined(__AVR_ATmega64M1__) || defined(__AVR_ATmega64C1__)
case EINT_0:
// Mask the interrupt so it doesn't fire anymore, i.e put a zero in the mask register.
EIMSK &= ~(1 << INT0);
break;
case EINT_1:
EIMSK &= ~(1 << INT1);
break;
....
default:
return GPIO_INT_OUT_OF_RANGE;
#else
#error "GPIO interrupts not implemented for this configuration."
#endif
}
答案 0 :(得分:4)
非贪婪的模式(如.*?
)并不神奇。
您显然希望.*?
中的(\<case:.*?\<break;\s*)+
(正则表达式的简化形式)与case:
不匹配。为什么不呢?换句话说,文字:
case 1:
do_something();
case 2:
do_something_else();
break;
肯定匹配case.*?break;
; .*?
匹配1: do_something(); case 2: do_something_else();
。
.*?
也不是围栏。如果case.*?break(more)
与第一个break
后面的文字不匹配,但与case
之后的文字相符,则(more)
可能与break
之后的第一个default:
不匹配第二个。
至于(default:)?
显然是可选的,这正是你的正则表达式所说的:
flex
我不认为正则表达式是可以挽救的。你不能用正则表达式解析C或C ++。
您确实需要使用更好的解析基础架构。您可以使用bison
和libclang
构建一个简单的解析器,它可以用于不与预处理器一起玩游戏的源代码,但您可能最好使用真正的C ++解析库,例如{{ 1}}。