ParseKit - 如何正确处理预处理器语句?

时间:2012-07-16 10:49:49

标签: objective-c parsing grammar parsekit

我为ParseKit编写了一个C语法,它确实可以正常工作,但让我疯狂的是预处理器语句。预处理器语句的正确符号定义是什么?

以下是我尝试过的简短例子......

@reportsCommentTokens = YES;
@commentState = '/';
@singleLineComments = '//';
@multiLineComments = '/*' '*/';
@commentState.fallbackState = delimitState;
@delimitState.fallbackState = symbolState;

@start = Empty | comments | preprocessor;

comments = comment*;
comment = Comment;

@symbols = '#include';

preprocessor = preprocessorIncludes;

preprocessorIncludes = preprocessorIncludeStatement*;
preprocessorIncludeStatement = preprocessorInclude quotedFileName*;

preprocessorInclude = '#include';
quotedFileName = QuotedString;

......但它不起作用。将其作为简化的语法示例来捕获注释并包含带引号的语句(不包含<>)。我在这个简单的文件上试过这个语法......

/*
 * Cryptographic API.
 *
 * RIPEMD-256 - RACE Integrity Primitives Evaluation Message Digest.
 *
 * Based on the reference implementation by Antoon Bosselaers, ESAT-COSIC
 *
 * Copyright (c) 2008 Adrian-Ken Rueegsegger <ken@codelabs.ch>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 */

// Here's one line comment

/* One line multiline comment */

#include "ripemd.h"

/* 2nd one line multiline comment */

...它以/ *一行多行注释* /结束,将其作为注释令牌报告,然后无声地失败。

所以我尝试将'#include'符号分隔为......

@symbolState = '#' '#';
@symbol = '#';
numSymbol = '#';

preprocessorInclude = numSymbol 'include';

......但它仍无济于事。

也许托德可以提供帮助,但处理像'#include'这样的'符号'的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

ParseKit的开发人员。

罗伯特,你的语法非常接近,但我发现你使用嵌套的*(零或多个)修饰符会导致语法失败。

我认为问题在于,您的@start语法制作已经Empty作为顶级选项(|与其他两个制作合作),但随后的子制作对于commentspreprocessor,两者都包含具有*(零或多个)修饰符的作品。那些*应该是+(一个或多个)修饰符,因为您已经使用顶级Empty计算了零个案例。

我不完全确定,但我认为这不是ParseKit独有的问题,而是我怀疑语法是有问题的,而且任何这样的语法工具包都可能出现这个问题。 (可能是错的)

考虑到这一点,语法的一些小调整已经为我修复了它。这是带有小调整的编辑语法:

@reportsCommentTokens = YES;
@commentState = '/';
@singleLineComments = '//';
@multiLineComments = '/*' '*/';
@commentState.fallbackState = delimitState;
@delimitState.fallbackState = symbolState;

@start = (comments | preprocessor)*;

comments = comment+;
comment = Comment;

@symbols = '#include';

preprocessor = preprocessorIncludes;

preprocessorIncludes = preprocessorIncludeStatement+;
preprocessorIncludeStatement = preprocessorInclude quotedFileName;

preprocessorInclude = '#include';
quotedFileName = QuotedString;

请注意我使用Empty替换了顶级的*。我用* s交换了嵌套的+

使用这个编辑过的语法,我得到了所需的输出(为了清晰起见,略微截断):

[/*
 * Cryptographic API.
...
 */, // Here's one line comment, /* One line multiline comment */, #include, "ripemd.h", /* 2nd one line multiline comment */]/*
 * Cryptographic API.
...
 *//// Here's one line comment//* One line multiline comment *//#include/"ripemd.h"//* 2nd one line multiline comment */^

另外,为了找到问题,我重写了语法更简单。以这种方式更容易找到问题。然后我重新应用了我发现的原始语法。这是我提出的简化语法,如果你感兴趣的话。这就是我想到的这个特殊语法:

@reportsCommentTokens = YES;
@commentState = '/';
@singleLineComments = '//';
@multiLineComments = '/*' '*/';

@start = (comment | macro)*;

comment = Comment;

macro = include; // to support other macros, add: ` | define | ifdef` etc.

include = '#' 'include' QuotedString;