【问题标题】:JSON parsing using Lemon (and Core Foundation)使用 Lemon(和 Core Foundation)解析 JSON
【发布时间】:2014-12-24 07:03:30
【问题描述】:

我正在尝试使用 Lemon 和 Apple Core Foundation 编写一个简单的 JSON 解析器。

到目前为止的代码如下:

%include {

#import <CoreFoundation/CoreFoundation.h>

#import "state.h" // struct ParserState { CFTypeRef result; };
#import "tuple.h" // struct Tuple { CFTypeRef one; CFTypeRef two; };

}

%start_symbol json

%token_type { CFTypeRef }
%token_prefix T

%extra_argument  { ParserStateRef state }

%type simple_value { CFTypeRef }
%type member { TupleRef }
%type members { CFMutableDictionaryRef }
%type object { CFMutableDictionaryRef }
%type array { CFMutableArrayRef }

simple_value(A) ::= STRING(B). { A = B; }
simple_value(A) ::= INT(B). { A = B; }
simple_value(A) ::= FLOAT(B). { A = B; }
simple_value(A) ::= FALSE. { A = kCFBooleanFalse; }
simple_value(A) ::= TRUE. { A = kCFBooleanTrue; }
simple_value(A) ::= NULL. { A = kCFNull; }

member(A) ::= STRING(B) COLON simple_value(C). {
    A = TupleCreate(B,C);
}
member ::= STRING COLON object.
member ::= STRING COLON array.

members(A) ::= member(B). {
    A = CFDictionaryCreateMutable(kCFAllocatorDefault,0,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(A, B->first, B->second);
    CFRelease(B->first);
    CFRelease(B->second);
    TupleRelease(B);
}
members(A) ::= members(B) COMMA member(C). {
    CFDictionarySetValue(B, C->first, C->second);
    CFRelease(C->first);
    CFRelease(C->second);
    TupleRelease(C);
    A = B;
}

values ::= value.
values ::= values COMMA value.

object(A) ::= LCB RCB. {
/* THIS NEVER GETS CALLED */
    A = CFDictionaryCreateMutable(kCFAllocatorDefault,0,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks);
}
object(A) ::= LCB members(B) RCB. {
/* THIS NEVER GETS CALLED */
    A = B;
}

array ::= LSB RSB.
array ::= LSB values RSB.

value ::= array.
value ::= object.
value ::= simple_value.

json ::= object(A). { state->result = A; }
json ::= array.

使用这样的简单 JSON

{ \"hello\" : \"world\" }

我无法超越 members 规则(此时,字典设置正确)。

object 规则永远不会被调用,json ::= object 也是如此!

我在做傻事吗?

我们将不胜感激!

【问题讨论】:

    标签: ios core-foundation lemon


    【解决方案1】:

    当令牌流用完时,您必须调用 Parser(...) 函数,第二个参数的值为零。

    信息来自:https://www.sqlite.org/src/doc/trunk/doc/lemon.html

       01 ParseTree *ParseFile(const char *zFilename){
       02    Tokenizer *pTokenizer;
       03    void *pParser;
       04    Token sToken;
       05    int hTokenId;
       06    ParserState sState;
       07
       08    pTokenizer = TokenizerCreate(zFilename);
       09    pParser = ParseAlloc( malloc );
       10    InitParserState(&sState);
       11    while( GetNextToken(pTokenizer, &hTokenId, &sToken) ){
       12       Parse(pParser, hTokenId, sToken, &sState);
       13    }
       14    Parse(pParser, 0, sToken, &sState);
       15    ParseFree(pParser, free );
       16    TokenizerFree(pTokenizer);
       17    return sState.treeRoot;
       18 }
    

    见第 14 行。它告诉解析器它不应该期望更多的令牌并且可以执行剩余的规则。

    基本上,程序要使用 Lemon 生成的解析器必须首先创建解析器,然后向它发送大量通过对输入源进行标记获得的标记。当到达输入结束时,Parse() 例程应该最后一次调用,标记类型为 0。这一步是通知解析器输入已经到达结束所必需的。最后,我们通过调用 ParseFree() 来回收解析器使用的内存。

    【讨论】:

      猜你喜欢
      • 2017-08-30
      • 1970-01-01
      • 2018-02-18
      • 2012-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多