2014-03-27 2 views
1

Это второй вопрос, связанный с Custom objects in ParseKit Actionsуправление Parser Stack во время грамматике с действиями

Если бы я имел правило грамматики, такие как:

qualifiedTableName = (databaseName '.')? tableName (('INDEXED' 'BY' indexName) | ('NOT' 'INDEXED'))?; 

Правомерно предположить, что действие не будет называться пока это правило не будет согласовано? Таким образом, в этом случае, когда действие вызывается в стек, может выглядеть так:

possibly: 
|'INDEXED' 
|'NOT' 
or: 
|indexName (A custom object possibly) 
|'BY' 
|'INDEXED 

|tableName (for sure will be here) 

and possibly these 
|'.'   (if this is here I know the database name must be here) if not push last one on? 
|databaseName 
--------------(perhaps more things from other rules) 

Эти правильные оценки? Есть ли другая документация по действиям? Я знаю, что это в значительной степени основано на Antlr, но его тонкие различия, которые могут действительно вызвать у вас проблемы.

ответ

1

Создатель PEGKit здесь.

Действия выполняются сразу после сопоставления предшествующего токена.

Пусть этот вход:

mydb.mytable INDEXED BY 'foo' 

Ваш пример правила не содержат каких-либо действий, поэтому я добавлю некоторые. Это действительно намного проще добавить действия, если вы сломать ваше правило на более мелкие подправил:

qualifiedTableName = name indexOpt 
{ 
    // now stack contains 3 `NSString`s. 
    // ["mydb", "mytable", "foo"] 
    NSString *indexName = POP(); 
    NSString *tableName = POP(); 
    NSString *dbName = POP(); 
    // do stuff here 
}; 

databaseName = Word; 
tableName = Word; 
indexName = QuotedString; 

name = (databaseName '.'!)? tableName 
{ 
    // now stack contains 2 `PKToken`s of type Word 
    // [<Word «mydb»>, <Word «mytable»>] 
    // pop their string values 
    NSString *tableName = POP_STR(); 
    NSString *dbName = POP_STR(); 
    PUSH(dbName); 
    PUSH(tableName); 
}; 

indexOpt 
    = index 
    | Empty { PUSH(@""); } 
    ; 

index 
    = ('INDEXED'! 'BY'! indexName) 
    { 
     // now top of stack will be a Quoted String `PKToken` 
     // […, <Quoted String «"foo"»>] 
     // pop its string value 
     NSString *indexName = POP_STR(); 
     // trim quotes 
     indexName = [indexName substringWithRange:NSMakeRange(1, [indexName length]-2)]; 
     // leave it on the stack for later 
     PUSH(indexName); 
    } 
    | ('NOT'! 'INDEXED'!) { PUSH(@""); } 
    ; 

Обратите внимание, что я отбрасывая все лексемы, используя директиву о ! отбрасывания. Эти литералы являются чистым синтаксисом и не нужны в ваших действиях для дальнейшей обработки.

Также обратите внимание, что в случае либо несуществующего выражения , либо выражения NOT INDEXED, я нажимаю пустую строку в стек. Это значит, что вы можете равномерно обрабатывать указанный индекс в действии qualifiedTableName. В этом Action вы всегда будете иметь строку в верхней части стека, которая указывает индекс. Если это пустая строка, то индекса нет.

+0

Для моего собственного понимания было бы целесообразно также изменить правило 'name', чтобы следовать тому же более гранулированному подходу вытащить значение' (databaseName '.')? 'Поскольку вы могли бы потенциально появиться нулевой объект. Или это нормально? например, разбор вашего примера без «mydb». будет правильно соответствовать, но имя dbname было бы nil Спасибо! – utahwithak

+0

Да, вы абсолютно правы. Я бы определенно нарушил это, чтобы упростить обработку присутствия или отсутствия имени, специфичного для db. –

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

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