2014-10-28 7 views
2

Я пытаюсь написать простой парсер JSON, используя Lemon и Apple Core Foundation.Анализ JSON с использованием Lemon (и Core Foundation)

Вот код до сих пор:

%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 :: = объект делает то же самое!

Я делаю что-то глупое?

Любой вход будет оценен!

ответ

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().

 Смежные вопросы

  • Нет связанных вопросов^_^