Управление стеком парсера во время грамматики с действиями


person utahwithak    schedule 27.03.2014    source источник


Ответы (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(@""); }
    ;

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

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

person Todd Ditchendorf    schedule 27.03.2014
comment
Насколько я понимаю, имеет ли смысл также изменить правило name, чтобы следовать тому же более детализированному подходу к извлечению (databaseName '.')?, поскольку вы потенциально можете вытолкнуть нулевой объект. Или это нормально? например, разбор вашего примера без mydb. будет соответствовать правильно, но имя базы данных будет нулевым. Спасибо! - person utahwithak; 27.03.2014
comment
Да, вы абсолютно правы. Я бы определенно выделил это для облегчения обработки наличия или отсутствия имени, специфичного для БД. - person Todd Ditchendorf; 27.03.2014