大量调用ANTLR38BitConsume库函数

时间:2015-10-14 09:11:42

标签: antlr3 lexical-analysis antlrworks

我正在使用ANTLR3为C目标编写ASN1的词法分析器,使用该库的3.4版本。实际上词法分析器真的很慢,所以我在执行时执行了一个perf记录,我发现瓶颈是库函数ANTLR38BitConsume,这非常简单。

static void
antlr38BitConsume(pANTLR3_INT_STREAM is)
{
pANTLR3_INPUT_STREAM input;


input   = ((pANTLR3_INPUT_STREAM) (is->super));

if  ((pANTLR3_UINT8)(input->nextChar) < (((pANTLR3_UINT8)input->data) +    input->sizeBuf))
{   
/* Indicate one more character in this line
 */
input->charPositionInLine++;

if  ((ANTLR3_UCHAR)(*((pANTLR3_UINT8)input->nextChar)) == input->newlineChar)
{
    /* Reset for start of a new line of input
     */
    input->line++;
    input->charPositionInLine   = 0;
    input->currentLine      = (void *)(((pANTLR3_UINT8)input->nextChar) +    1);
}

/* Increment to next character position
 */
input->nextChar = (void *)(((pANTLR3_UINT8)input->nextChar) + 1);
}
} 

经过调查,我发现在一个大小为1.4KB的文件中,这个函数,我认为每个字节最多应调用一次,它被称为24.5M次。你知道这是一个已知的问题还是对这种奇怪的行为有另一种解释?

EDITED

经过一些试验,我已经找出导致这个问题的规则。我有一些规则来识别特定的对象标识符,这很简单:

 OID1 : {counter==6}?=> 2 3 4 5 840 {counter=0;} 

和一个匹配ASN1编码的内容字段中每个字节的规则:

 VALUE : ({counter>0}?=> '\u0000'..'\u00FF' {counter--;})+

由于词法分析器使用最长匹配规则,因此永远不会匹配OID1,因为VALUE可以匹配任意长值。因此,为了欺骗词法分析器,我以这种方式编辑OID1规则:

OID1 : {counter==6}?=> 2 3 4 5 840 {counter=0;} VALUE?

规则末尾的VALUE令牌永远不会匹配,因为该规则仅在counter大于0时才有效,但这样lexer在匹配时也会考虑OID1,因为它可能比值。 但是,这个规则导致了对BitConsume函数的大量调用!一旦删除VALUE?部分,我得到了一些调用,精确等于输入文件的字节数。 我认为这是ANTLR的实现错误,因为它应该尝试将OID1之后的输入与VALUE匹配,但它应该立即停止并跳过令牌,因为计数器为0.

0 个答案:

没有答案