Как пропустить несвязанные строки при использовании Perl 6 Grammar для анализа структурированного текста?

Я хочу стереть .sql файл, используя Perl 6 Grammar, интересно, могу ли я пропустить некоторые несвязанные строки во время синтаксического анализа?

Например: я хочу пропустить DROP строк, /*!....!*/ строк, -- строк и пробел за пределами блока CREATE TABLE в следующем тексте.

То есть я хочу сосредоточиться на CREATE TABLE блоках:

    DROP TABLE IF EXISTS `abcd`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `abcd` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'app_id',
  `username` varchar(255) DEFAULT NULL COMMENT 'username',
  `url` varbinary(255) DEFAULT NULL COMMENT 'url',
  PRIMARY KEY (`id`),
  UNIQUE KEY `NewIndex1` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=954 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Table structure for table `temp`
--

DROP TABLE IF EXISTS `temp`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `temp` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `address` varchar(15) NOT NULL,
  `name` varchar(50) DEFAULT NULL,
  `phone_model` varchar(10) NOT NULL,
  `expire_time` varchar(15) NOT NULL,
  `created` varchar(15) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1496 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

Есть какие-нибудь предложения?


person ohmycloudy    schedule 15.02.2017    source источник


Ответы (2)


Как насчет того, чтобы просто выбросить значения в классе действий.

grammar SQL {
  token TOP { <command>+ %% \n }
  token command { <create-table> | <drop-table> | ... }
  token drop-table { ... }
  token create-table { ... }
  ...
}

class Create-only {
  method TOP ($/) { make @<command>».made }
  method command ($/) {
    make $/.values[0].made
  }
  method drop-table ($/) { make Empty }
  method create-table ($/) {
    make %( $/.pairs.map: {.key => .value.made} )
    # or whatever you need to to pass through the made values
  }
  ...
}

SQL.parse($text,:actions(Create-only)).made;

быстрый пример, показывающий, что это может работать:

grammar :: {
  token TOP { <c>+ %% \n }
  token c {<a>|<b>}
  token a {a}
  token b {b}
}.parse(

  'abbbaab'.comb.join("\n"),

  :actions(class :: {
    method TOP ($/){make @<c>».made}
    method a ($/){make ~$/}
    method b ($/){make Empty}
    method c($/){make $/.values[0].made }
  })
).made.say
[a a a]
person Brad Gilbert    schedule 15.02.2017
comment
приятно 1_! ха-ха - person ohmycloudy; 16.02.2017

Если вы используете «правило» вместо «токена», например, с грамматикой SQL в ответе Брэда, любые пробелы после атома превращаются в не захватывающий вызов <ws>, поэтому вы можете переопределить <ws> (пробел), чтобы включить другие вещи вы хотите игнорировать, например, комментарии:

token ws { \s* | <slash-star-comment>* | <dashes-comment>* }
token slash-star-comment { \s* '/*!' .*? '!*/' \s* }
token dashes-comment { \s* '--' \N* \s* }

Я разместил там \ s *, чтобы вы могли оставить пробелы до или после комментариев.

person Curt Tilmes    schedule 15.02.2017