2014-10-28 63 views
2

我想用檸檬和蘋果核心基金會編寫一個簡單的JSON解析器。使用檸檬(和核心基金會)解析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\" } 

我不能走過去的成員規則(在這一點上,詞典設置正確地)。

對象規則永遠不會被調用,並且json :: = object也是這樣做的!

我在做一些愚蠢的事情嗎?

任何輸入將不勝感激!

回答

0

當令牌流用完時,您必須調用第二個參數爲零值的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.它說,分析器,它不應該指望更多的標記,並可以執行依然規則。

基本上,使用檸檬生成的解析器需要做的事情是首先創建解析器,然後通過標記輸入源來發送大量的標記。當到達輸入結束時,Parse()例程應該被最後一次調用,標記類型爲0.這個步驟對於通知解析器輸入已到達結束是必要的。最後,我們通過調用ParseFree()來回收解析器使用的內存。