How to use TokenMatcher class

Best Gherkin-php code snippet using TokenMatcher

MatcherFactory.php

Source:MatcherFactory.php Github

copy

Full Screen

...58 * @return Matcher59 */60 public function comma() {61 if ( !isset( $this->cache[__METHOD__] ) ) {62 $this->cache[__METHOD__] = new TokenMatcher( Token::T_COMMA );63 }64 return $this->cache[__METHOD__];65 }66 /**67 * Matcher for an arbitrary identifier68 * @return Matcher69 */70 public function ident() {71 if ( !isset( $this->cache[__METHOD__] ) ) {72 $this->cache[__METHOD__] = new TokenMatcher( Token::T_IDENT );73 }74 return $this->cache[__METHOD__];75 }76 /**77 * Matcher for a string78 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#strings79 * @warning If the string will be used as a URL, use self::urlstring() instead.80 * @return Matcher81 */82 public function string() {83 if ( !isset( $this->cache[__METHOD__] ) ) {84 $this->cache[__METHOD__] = new TokenMatcher( Token::T_STRING );85 }86 return $this->cache[__METHOD__];87 }88 /**89 * Matcher for a string containing a URL90 * @param string $type Type of resource referenced, e.g. "image" or "audio".91 * Not used here, but might be used by a subclass to validate the URL more strictly.92 * @return Matcher93 */94 public function urlstring( $type ) {95 return $this->string();96 }97 /**98 * Matcher for a URL99 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#urls100 * @param string $type Type of resource referenced, e.g. "image" or "audio".101 * Not used here, but might be used by a subclass to validate the URL more strictly.102 * @return Matcher103 */104 public function url( $type ) {105 if ( !isset( $this->cache[__METHOD__] ) ) {106 $this->cache[__METHOD__] = new UrlMatcher();107 }108 return $this->cache[__METHOD__];109 }110 /**111 * CSS-wide value keywords112 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#common-keywords113 * @return Matcher114 */115 public function cssWideKeywords() {116 if ( !isset( $this->cache[__METHOD__] ) ) {117 $this->cache[__METHOD__] = new KeywordMatcher( [ 'initial', 'inherit', 'unset' ] );118 }119 return $this->cache[__METHOD__];120 }121 /**122 * Add calc() support to a basic type matcher123 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#calc-notation124 * @param Matcher $typeMatcher Matcher for the type125 * @param string $type Type being matched126 * @return Matcher127 */128 public function calc( Matcher $typeMatcher, $type ) {129 if ( $type === 'integer' ) {130 $num = $this->rawInteger();131 } else {132 $num = $this->rawNumber();133 }134 $ows = $this->optionalWhitespace();135 $ws = $this->significantWhitespace();136 // Definitions are recursive. This will be used by reference and later137 // will be replaced.138 $calcValue = new NothingMatcher();139 if ( $type === 'integer' ) {140 // Division will always resolve to a number, making the expression141 // invalid, so don't allow it.142 $calcProduct = new Juxtaposition( [143 &$calcValue,144 Quantifier::star( new Juxtaposition( [ $ows, new DelimMatcher( '*' ), $ows, &$calcValue ] ) )145 ] );146 } else {147 $calcProduct = new Juxtaposition( [148 &$calcValue,149 Quantifier::star( new Alternative( [150 new Juxtaposition( [ $ows, new DelimMatcher( '*' ), $ows, &$calcValue ] ),151 new Juxtaposition( [ $ows, new DelimMatcher( '/' ), $ows, $this->rawNumber() ] ),152 ] ) ),153 ] );154 }155 $calcSum = new Juxtaposition( [156 $ows,157 $calcProduct,158 Quantifier::star( new Juxtaposition( [159 $ws, new DelimMatcher( [ '+', '-' ] ), $ws, $calcProduct160 ] ) ),161 $ows,162 ] );163 $calcFunc = new FunctionMatcher( 'calc', $calcSum );164 if ( $num === $typeMatcher ) {165 $calcValue = new Alternative( [166 $typeMatcher,167 new BlockMatcher( Token::T_LEFT_PAREN, $calcSum ),168 $calcFunc,169 ] );170 } else {171 $calcValue = new Alternative( [172 $num,173 $typeMatcher,174 new BlockMatcher( Token::T_LEFT_PAREN, $calcSum ),175 $calcFunc,176 ] );177 }178 return new Alternative( [ $typeMatcher, $calcFunc ] );179 }180 /**181 * Matcher for an integer value, without calc()182 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#integers183 * @return Matcher184 */185 protected function rawInteger() {186 if ( !isset( $this->cache[__METHOD__] ) ) {187 $this->cache[__METHOD__] = new TokenMatcher( Token::T_NUMBER, function ( Token $t ) {188 // The spec says it must match /^[+-]\d+$/, but the tokenizer189 // should have marked any other number token as a 'number'190 // anyway so let's not bother checking.191 return $t->typeFlag() === 'integer';192 } );193 }194 return $this->cache[__METHOD__];195 }196 /**197 * Matcher for an integer value198 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#integers199 * @return Matcher200 */201 public function integer() {202 if ( !isset( $this->cache[__METHOD__] ) ) {203 $this->cache[__METHOD__] = $this->calc( $this->rawInteger(), 'integer' );204 }205 return $this->cache[__METHOD__];206 }207 /**208 * Matcher for a real number, without calc()209 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#numbers210 * @return Matcher211 */212 public function rawNumber() {213 if ( !isset( $this->cache[__METHOD__] ) ) {214 $this->cache[__METHOD__] = new TokenMatcher( Token::T_NUMBER );215 }216 return $this->cache[__METHOD__];217 }218 /**219 * Matcher for a real number220 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#numbers221 * @return Matcher222 */223 public function number() {224 if ( !isset( $this->cache[__METHOD__] ) ) {225 $this->cache[__METHOD__] = $this->calc( $this->rawNumber(), 'number' );226 }227 return $this->cache[__METHOD__];228 }229 /**230 * Matcher for a percentage value, without calc()231 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#percentages232 * @return Matcher233 */234 public function rawPercentage() {235 if ( !isset( $this->cache[__METHOD__] ) ) {236 $this->cache[__METHOD__] = new TokenMatcher( Token::T_PERCENTAGE );237 }238 return $this->cache[__METHOD__];239 }240 /**241 * Matcher for a percentage value242 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#percentages243 * @return Matcher244 */245 public function percentage() {246 if ( !isset( $this->cache[__METHOD__] ) ) {247 $this->cache[__METHOD__] = $this->calc( $this->rawPercentage(), 'percentage' );248 }249 return $this->cache[__METHOD__];250 }251 /**252 * Matcher for a length-percentage value253 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#typedef-length-percentage254 * @return Matcher255 */256 public function lengthPercentage() {257 if ( !isset( $this->cache[__METHOD__] ) ) {258 $this->cache[__METHOD__] = $this->calc(259 new Alternative( [ $this->rawLength(), $this->rawPercentage() ] ),260 'length'261 );262 }263 return $this->cache[__METHOD__];264 }265 /**266 * Matcher for a frequency-percentage value267 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#typedef-frequency-percentage268 * @return Matcher269 */270 public function frequencyPercentage() {271 if ( !isset( $this->cache[__METHOD__] ) ) {272 $this->cache[__METHOD__] = $this->calc(273 new Alternative( [ $this->rawFrequency(), $this->rawPercentage() ] ),274 'frequency'275 );276 }277 return $this->cache[__METHOD__];278 }279 /**280 * Matcher for a angle-percentage value281 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#typedef-angle-percentage282 * @return Matcher283 */284 public function anglePercentage() {285 if ( !isset( $this->cache[__METHOD__] ) ) {286 $this->cache[__METHOD__] = $this->calc(287 new Alternative( [ $this->rawAngle(), $this->rawPercentage() ] ),288 'angle'289 );290 }291 return $this->cache[__METHOD__];292 }293 /**294 * Matcher for a time-percentage value295 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#typedef-time-percentage296 * @return Matcher297 */298 public function timePercentage() {299 if ( !isset( $this->cache[__METHOD__] ) ) {300 $this->cache[__METHOD__] = $this->calc(301 new Alternative( [ $this->rawTime(), $this->rawPercentage() ] ),302 'time'303 );304 }305 return $this->cache[__METHOD__];306 }307 /**308 * Matcher for a number-percentage value309 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#typedef-number-percentage310 * @return Matcher311 */312 public function numberPercentage() {313 if ( !isset( $this->cache[__METHOD__] ) ) {314 $this->cache[__METHOD__] = $this->calc(315 new Alternative( [ $this->rawNumber(), $this->rawPercentage() ] ),316 'number'317 );318 }319 return $this->cache[__METHOD__];320 }321 /**322 * Matcher for a dimension value323 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#dimensions324 * @return Matcher325 */326 public function dimension() {327 if ( !isset( $this->cache[__METHOD__] ) ) {328 $this->cache[__METHOD__] = new TokenMatcher( Token::T_DIMENSION );329 }330 return $this->cache[__METHOD__];331 }332 /**333 * Matches the number 0334 * @return Matcher335 */336 protected function zero() {337 if ( !isset( $this->cache[__METHOD__] ) ) {338 $this->cache[__METHOD__] = new TokenMatcher( Token::T_NUMBER, function ( Token $t ) {339 return $t->value() === 0 || $t->value() === 0.0;340 } );341 }342 return $this->cache[__METHOD__];343 }344 /**345 * Matcher for a length value, without calc()346 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#lengths347 * @return Matcher348 */349 protected function rawLength() {350 if ( !isset( $this->cache[__METHOD__] ) ) {351 $unitsRe = '/^(' . join( '|', self::$lengthUnits ) . ')$/i';352 $this->cache[__METHOD__] = new Alternative( [353 $this->zero(),354 new TokenMatcher( Token::T_DIMENSION, function ( Token $t ) use ( $unitsRe ) {355 return preg_match( $unitsRe, $t->unit() );356 } ),357 ] );358 }359 return $this->cache[__METHOD__];360 }361 /**362 * Matcher for a length value363 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#lengths364 * @return Matcher365 */366 public function length() {367 if ( !isset( $this->cache[__METHOD__] ) ) {368 $this->cache[__METHOD__] = $this->calc( $this->rawLength(), 'length' );369 }370 return $this->cache[__METHOD__];371 }372 /**373 * Matcher for an angle value, without calc()374 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#angles375 * @return Matcher376 */377 protected function rawAngle() {378 if ( !isset( $this->cache[__METHOD__] ) ) {379 $unitsRe = '/^(' . join( '|', self::$angleUnits ) . ')$/i';380 $this->cache[__METHOD__] = new Alternative( [381 $this->zero(),382 new TokenMatcher( Token::T_DIMENSION, function ( Token $t ) use ( $unitsRe ) {383 return preg_match( $unitsRe, $t->unit() );384 } ),385 ] );386 }387 return $this->cache[__METHOD__];388 }389 /**390 * Matcher for an angle value391 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#angles392 * @return Matcher393 */394 public function angle() {395 if ( !isset( $this->cache[__METHOD__] ) ) {396 $this->cache[__METHOD__] = $this->calc( $this->rawAngle(), 'angle' );397 }398 return $this->cache[__METHOD__];399 }400 /**401 * Matcher for a duration (time) value, without calc()402 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#time403 * @return Matcher404 */405 protected function rawTime() {406 if ( !isset( $this->cache[__METHOD__] ) ) {407 $unitsRe = '/^(' . join( '|', self::$timeUnits ) . ')$/i';408 $this->cache[__METHOD__] = new TokenMatcher( Token::T_DIMENSION,409 function ( Token $t ) use ( $unitsRe ) {410 return preg_match( $unitsRe, $t->unit() );411 }412 );413 }414 return $this->cache[__METHOD__];415 }416 /**417 * Matcher for a duration (time) value418 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#time419 * @return Matcher420 */421 public function time() {422 if ( !isset( $this->cache[__METHOD__] ) ) {423 $this->cache[__METHOD__] = $this->calc( $this->rawTime(), 'time' );424 }425 return $this->cache[__METHOD__];426 }427 /**428 * Matcher for a frequency value, without calc()429 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#frequency430 * @return Matcher431 */432 protected function rawFrequency() {433 if ( !isset( $this->cache[__METHOD__] ) ) {434 $unitsRe = '/^(' . join( '|', self::$frequencyUnits ) . ')$/i';435 $this->cache[__METHOD__] = new TokenMatcher( Token::T_DIMENSION,436 function ( Token $t ) use ( $unitsRe ) {437 return preg_match( $unitsRe, $t->unit() );438 }439 );440 }441 return $this->cache[__METHOD__];442 }443 /**444 * Matcher for a frequency value445 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#frequency446 * @return Matcher447 */448 public function frequency() {449 if ( !isset( $this->cache[__METHOD__] ) ) {450 $this->cache[__METHOD__] = $this->calc( $this->rawFrequency(), 'frequency' );451 }452 return $this->cache[__METHOD__];453 }454 /**455 * Matcher for a resolution value456 * @see https://www.w3.org/TR/2016/CR-css-values-3-20160929/#resolution457 * @return Matcher458 */459 public function resolution() {460 if ( !isset( $this->cache[__METHOD__] ) ) {461 $this->cache[__METHOD__] = new TokenMatcher( Token::T_DIMENSION, function ( Token $t ) {462 return preg_match( '/^(dpi|dpcm|dppx)$/i', $t->unit() );463 } );464 }465 return $this->cache[__METHOD__];466 }467 /**468 * Matchers for color functions469 * @return Matcher[]470 */471 protected function colorFuncs() {472 if ( !isset( $this->cache[__METHOD__] ) ) {473 $i = $this->integer();474 $n = $this->number();475 $p = $this->percentage();476 $this->cache[__METHOD__] = [477 new FunctionMatcher( 'rgb', new Alternative( [478 Quantifier::hash( $i, 3, 3 ),479 Quantifier::hash( $p, 3, 3 ),480 ] ) ),481 new FunctionMatcher( 'rgba', new Alternative( [482 new Juxtaposition( [ $i, $i, $i, $n ], true ),483 new Juxtaposition( [ $p, $p, $p, $n ], true ),484 ] ) ),485 new FunctionMatcher( 'hsl', new Juxtaposition( [ $n, $p, $p ], true ) ),486 new FunctionMatcher( 'hsla', new Juxtaposition( [ $n, $p, $p, $n ], true ) ),487 ];488 }489 return $this->cache[__METHOD__];490 }491 /**492 * Matcher for a color value493 * @see https://www.w3.org/TR/2011/REC-css3-color-20110607/#colorunits494 * @return Matcher495 */496 public function color() {497 if ( !isset( $this->cache[__METHOD__] ) ) {498 $this->cache[__METHOD__] = new Alternative( array_merge( [499 new KeywordMatcher( [500 // Basic colors501 'aqua', 'black', 'blue', 'fuchsia', 'gray', 'green',502 'lime', 'maroon', 'navy', 'olive', 'purple', 'red',503 'silver', 'teal', 'white', 'yellow',504 // Extended colors505 'aliceblue', 'antiquewhite', 'aquamarine', 'azure',506 'beige', 'bisque', 'blanchedalmond', 'blueviolet', 'brown',507 'burlywood', 'cadetblue', 'chartreuse', 'chocolate',508 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan',509 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray',510 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta',511 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred',512 'darksalmon', 'darkseagreen', 'darkslateblue',513 'darkslategray', 'darkslategrey', 'darkturquoise',514 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray',515 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite',516 'forestgreen', 'gainsboro', 'ghostwhite', 'gold',517 'goldenrod', 'greenyellow', 'grey', 'honeydew', 'hotpink',518 'indianred', 'indigo', 'ivory', 'khaki', 'lavender',519 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue',520 'lightcoral', 'lightcyan', 'lightgoldenrodyellow',521 'lightgray', 'lightgreen', 'lightgrey', 'lightpink',522 'lightsalmon', 'lightseagreen', 'lightskyblue',523 'lightslategray', 'lightslategrey', 'lightsteelblue',524 'lightyellow', 'limegreen', 'linen', 'magenta',525 'mediumaquamarine', 'mediumblue', 'mediumorchid',526 'mediumpurple', 'mediumseagreen', 'mediumslateblue',527 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred',528 'midnightblue', 'mintcream', 'mistyrose', 'moccasin',529 'navajowhite', 'oldlace', 'olivedrab', 'orange',530 'orangered', 'orchid', 'palegoldenrod', 'palegreen',531 'paleturquoise', 'palevioletred', 'papayawhip',532 'peachpuff', 'peru', 'pink', 'plum', 'powderblue',533 'rosybrown', 'royalblue', 'saddlebrown', 'salmon',534 'sandybrown', 'seagreen', 'seashell', 'sienna', 'skyblue',535 'slateblue', 'slategray', 'slategrey', 'snow',536 'springgreen', 'steelblue', 'tan', 'thistle', 'tomato',537 'turquoise', 'violet', 'wheat', 'whitesmoke',538 'yellowgreen',539 // Other keywords. Intentionally omitting the deprecated system colors.540 'transparent', 'currentColor',541 ] ),542 new TokenMatcher( Token::T_HASH, function ( Token $t ) {543 return preg_match( '/^([0-9a-f]{3}|[0-9a-f]{6})$/i', $t->value() );544 } ),545 ], $this->colorFuncs() ) );546 }547 return $this->cache[__METHOD__];548 }549 /**550 * Matcher for an image value551 * @see https://www.w3.org/TR/2012/CR-css3-images-20120417/#image-values552 * @return Matcher553 */554 public function image() {555 if ( !isset( $this->cache[__METHOD__] ) ) {556 // https://www.w3.org/TR/2012/CR-css3-images-20120417/#image-list-type557 // Note the undefined <element-reference> production has been dropped from the Editor's Draft.558 $imageDecl = new Alternative( [559 $this->url( 'image' ),560 $this->urlstring( 'image' ),561 ] );562 // https://www.w3.org/TR/2012/CR-css3-images-20120417/#gradients563 $c = $this->comma();564 $colorStops = Quantifier::hash( new Juxtaposition( [565 $this->color(),566 // Not really <length-percentage>, but grammatically the same567 Quantifier::optional( $this->lengthPercentage() ),568 ] ), 2, INF );569 $atPosition = new Juxtaposition( [ new KeywordMatcher( 'at' ), $this->position() ] );570 $linearGradient = new Juxtaposition( [571 Quantifier::optional( new Juxtaposition( [572 new Alternative( [573 $this->angle(),574 new Juxtaposition( [ new KeywordMatcher( 'to' ), UnorderedGroup::someOf( [575 new KeywordMatcher( [ 'left', 'right' ] ),576 new KeywordMatcher( [ 'top', 'bottom' ] ),577 ] ) ] )578 ] ),579 $c580 ] ) ),581 $colorStops,582 ] );583 $radialGradient = new Juxtaposition( [584 Quantifier::optional( new Juxtaposition( [585 new Alternative( [586 new Juxtaposition( [587 new Alternative( [588 UnorderedGroup::someOf( [ new KeywordMatcher( 'circle' ), $this->length() ] ),589 UnorderedGroup::someOf( [590 new KeywordMatcher( 'ellipse' ),591 // Not really <length-percentage>, but grammatically the same592 Quantifier::count( $this->lengthPercentage(), 2, 2 )593 ] ),594 UnorderedGroup::someOf( [595 new KeywordMatcher( [ 'circle', 'ellipse' ] ),596 new KeywordMatcher( [597 'closest-side', 'farthest-side', 'closest-corner', 'farthest-corner'598 ] ),599 ] ),600 ] ),601 Quantifier::optional( $atPosition ),602 ] ),603 $atPosition604 ] ),605 $c606 ] ) ),607 $colorStops,608 ] );609 // Putting it all together610 $this->cache[__METHOD__] = new Alternative( [611 $this->url( 'image' ),612 new FunctionMatcher( 'image', new Juxtaposition( [613 Quantifier::star( new Juxtaposition( [ $imageDecl, $c ] ) ),614 new Alternative( [ $imageDecl, $this->color() ] ),615 ] ) ),616 new FunctionMatcher( 'linear-gradient', $linearGradient ),617 new FunctionMatcher( 'radial-gradient', $radialGradient ),618 new FunctionMatcher( 'repeating-linear-gradient', $linearGradient ),619 new FunctionMatcher( 'repeating-radial-gradient', $radialGradient ),620 ] );621 }622 return $this->cache[__METHOD__];623 }624 /**625 * Matcher for a position value626 * @see https://www.w3.org/TR/2014/CR-css3-background-20140909/#ltpositiongt627 * @return Matcher628 */629 public function position() {630 if ( !isset( $this->cache[__METHOD__] ) ) {631 $lp = $this->lengthPercentage();632 $olp = Quantifier::optional( $lp );633 $center = new KeywordMatcher( 'center' );634 $leftRight = new KeywordMatcher( [ 'left', 'right' ] );635 $topBottom = new KeywordMatcher( [ 'top', 'bottom' ] );636 $this->cache[__METHOD__] = new Alternative( [637 new Alternative( [ $center, $leftRight, $topBottom, $lp ] ),638 new Juxtaposition( [639 new Alternative( [ $center, $leftRight, $lp ] ),640 new Alternative( [ $center, $topBottom, $lp ] ),641 ] ),642 UnorderedGroup::allOf( [643 new Alternative( [ $center, new Juxtaposition( [ $leftRight, $olp ] ) ] ),644 new Alternative( [ $center, new Juxtaposition( [ $topBottom, $olp ] ) ] ),645 ] ),646 ] );647 }648 return $this->cache[__METHOD__];649 }650 /**651 * Matcher for a CSS media query652 * @see https://www.w3.org/TR/2016/WD-mediaqueries-4-20160706/#mq-syntax653 * @param bool $strict Only allow defined query types654 * @return Matcher655 */656 public function cssMediaQuery( $strict = true ) {657 $key = __METHOD__ . ':' . ( $strict ? 'strict' : 'unstrict' );658 if ( !isset( $this->cache[$key] ) ) {659 if ( $strict ) {660 $generalEnclosed = new NothingMatcher();661 $mediaType = new KeywordMatcher( [662 'all', 'print', 'screen', 'speech',663 // deprecated664 'tty', 'tv', 'projection', 'handheld', 'braille', 'embossed', 'aural'665 ] );666 $rangeFeatures = [667 'width', 'height', 'aspect-ratio', 'resolution', 'color', 'color-index', 'monochrome',668 // deprecated669 'device-width', 'device-height', 'device-aspect-ratio'670 ];671 $discreteFeatures = [672 'orientation', 'scan', 'grid', 'update', 'overflow-block', 'overflow-inline', 'color-gamut',673 'pointer', 'hover', 'any-pointer', 'any-hover', 'scripting'674 ];675 $mfName = new KeywordMatcher( array_merge(676 $rangeFeatures,677 array_map( function ( $f ) {678 return "min-$f";679 }, $rangeFeatures ),680 array_map( function ( $f ) {681 return "max-$f";682 }, $rangeFeatures ),683 $discreteFeatures684 ) );685 } else {686 $anythingPlus = new AnythingMatcher( [ 'quantifier' => '+' ] );687 $generalEnclosed = new Alternative( [688 new FunctionMatcher( null, $anythingPlus ),689 new BlockMatcher( Token::T_LEFT_PAREN,690 new Juxtaposition( [ $this->ident(), $anythingPlus ] )691 ),692 ] );693 $mediaType = $this->ident();694 $mfName = $this->ident();695 }696 $posInt = $this->calc(697 new TokenMatcher( Token::T_NUMBER, function ( Token $t ) {698 return $t->typeFlag() === 'integer' && preg_match( '/^\+?\d+$/', $t->representation() );699 } ),700 'integer'701 );702 $eq = new DelimMatcher( '=' );703 $oeq = Quantifier::optional( new Juxtaposition( [ new NoWhitespace, $eq ] ) );704 $ltgteq = Quantifier::optional( new Alternative( [705 $eq,706 new Juxtaposition( [ new DelimMatcher( [ '<', '>' ] ), $oeq ] ),707 ] ) );708 $lteq = new Juxtaposition( [ new DelimMatcher( '<' ), $oeq ] );709 $gteq = new Juxtaposition( [ new DelimMatcher( '>' ), $oeq ] );710 $mfValue = new Alternative( [711 $this->number(),712 $this->dimension(),713 $this->ident(),714 new Juxtaposition( [ $posInt, new DelimMatcher( '/' ), $posInt ] ),715 ] );716 $mediaInParens = new NothingMatcher(); // temporary717 $mediaNot = new Juxtaposition( [ new KeywordMatcher( 'not' ), &$mediaInParens ] );718 $mediaAnd = new Juxtaposition( [719 &$mediaInParens,720 Quantifier::plus( new Juxtaposition( [ new KeywordMatcher( 'and' ), &$mediaInParens ] ) )721 ] );722 $mediaOr = new Juxtaposition( [723 &$mediaInParens,724 Quantifier::plus( new Juxtaposition( [ new KeywordMatcher( 'or' ), &$mediaInParens ] ) )725 ] );726 $mediaCondition = new Alternative( [ $mediaNot, $mediaAnd, $mediaOr, &$mediaInParens ] );727 $mediaConditionWithoutOr = new Alternative( [ $mediaNot, $mediaAnd, &$mediaInParens ] );728 $mediaFeature = new BlockMatcher( Token::T_LEFT_PAREN, new Alternative( [729 new Juxtaposition( [ $mfName, new TokenMatcher( Token::T_COLON ), $mfValue ] ), // <mf-plain>730 $mfName, // <mf-boolean>731 new Juxtaposition( [ $mfName, $ltgteq, $mfValue ] ), // <mf-range>, 1st alternative732 new Juxtaposition( [ $mfValue, $ltgteq, $mfName ] ), // <mf-range>, 2nd alternative733 new Juxtaposition( [ $mfValue, $lteq, $mfName, $lteq, $mfValue ] ), // <mf-range>, 3rd alt734 new Juxtaposition( [ $mfValue, $gteq, $mfName, $gteq, $mfValue ] ), // <mf-range>, 4th alt735 ] ) );736 $mediaInParens = new Alternative( [737 new BlockMatcher( Token::T_LEFT_PAREN, $mediaCondition ),738 $mediaFeature,739 $generalEnclosed,740 ] );741 $this->cache[$key] = new Alternative( [742 $mediaCondition,743 new Juxtaposition( [744 Quantifier::optional( new KeywordMatcher( [ 'not', 'only' ] ) ),745 $mediaType,746 Quantifier::optional( new Juxtaposition( [747 new KeywordMatcher( 'and' ),748 $mediaConditionWithoutOr,749 ] ) )750 ] )751 ] );752 }753 return $this->cache[$key];754 }755 /**756 * Matcher for a CSS media query list757 * @see https://www.w3.org/TR/2016/WD-mediaqueries-4-20160706/#mq-syntax758 * @param bool $strict Only allow defined query types759 * @return Matcher760 */761 public function cssMediaQueryList( $strict = true ) {762 $key = __METHOD__ . ':' . ( $strict ? 'strict' : 'unstrict' );763 if ( !isset( $this->cache[$key] ) ) {764 $this->cache[$key] = Quantifier::hash( $this->cssMediaQuery( $strict ), 0, INF );765 }766 return $this->cache[$key];767 }768 /************************************************************************//**769 * @name CSS Selectors Level 3770 * @{771 *772 * https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#w3cselgrammar773 */774 /**775 * List of selectors776 *777 * selector [ COMMA S* selector ]*778 *779 * Capturing is set up for the `selector`s.780 *781 * @return Matcher782 */783 public function cssSelectorList() {784 if ( !isset( $this->cache[__METHOD__] ) ) {785 // Technically the spec doesn't allow whitespace before the comma,786 // but I'd guess every browser does. So just use Quantifier::hash.787 $selector = $this->cssSelector()->capture( 'selector' );788 $this->cache[__METHOD__] = Quantifier::hash( $selector );789 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );790 }791 return $this->cache[__METHOD__];792 }793 /**794 * A single selector795 *796 * simple_selector_sequence [ combinator simple_selector_sequence ]*797 *798 * Capturing is set up for the `simple_selector_sequence`s (as 'simple') and `combinator`.799 *800 * @return Matcher801 */802 public function cssSelector() {803 if ( !isset( $this->cache[__METHOD__] ) ) {804 $simple = $this->cssSimpleSelectorSeq()->capture( 'simple' );805 $this->cache[__METHOD__] = new Juxtaposition( [806 $simple,807 Quantifier::star( new Juxtaposition( [808 $this->cssCombinator()->capture( 'combinator' ),809 $simple,810 ] ) )811 ] );812 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );813 }814 return $this->cache[__METHOD__];815 }816 /**817 * A CSS combinator818 *819 * PLUS S* | GREATER S* | TILDE S* | S+820 *821 * (combinators can be surrounded by whitespace)822 *823 * @return Matcher824 */825 public function cssCombinator() {826 if ( !isset( $this->cache[__METHOD__] ) ) {827 $this->cache[__METHOD__] = new Alternative( [828 new Juxtaposition( [829 $this->optionalWhitespace(),830 new DelimMatcher( [ '+', '>', '~' ] ),831 $this->optionalWhitespace(),832 ] ),833 $this->significantWhitespace(),834 ] );835 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );836 }837 return $this->cache[__METHOD__];838 }839 /**840 * A simple selector sequence841 *842 * [ type_selector | universal ]843 * [ HASH | class | attrib | pseudo | negation ]*844 * | [ HASH | class | attrib | pseudo | negation ]+845 *846 * The following captures are set:847 * - element: [ type_selector | universal ]848 * - id: HASH849 * - class: class850 * - attrib: attrib851 * - pseudo: pseudo852 * - negation: negation853 *854 * @return Matcher855 */856 public function cssSimpleSelectorSeq() {857 if ( !isset( $this->cache[__METHOD__] ) ) {858 $hashEtc = new Alternative( [859 $this->cssID()->capture( 'id' ),860 $this->cssClass()->capture( 'class' ),861 $this->cssAttrib()->capture( 'attrib' ),862 $this->cssPseudo()->capture( 'pseudo' ),863 $this->cssNegation()->capture( 'negation' ),864 ] );865 $this->cache[__METHOD__] = new Alternative( [866 new Juxtaposition( [867 Alternative::create( [868 $this->cssTypeSelector(),869 $this->cssUniversal(),870 ] )->capture( 'element' ),871 Quantifier::star( $hashEtc )872 ] ),873 Quantifier::plus( $hashEtc )874 ] );875 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );876 }877 return $this->cache[__METHOD__];878 }879 /**880 * A type selector (i.e. a tag name)881 *882 * [ namespace_prefix ] ? element_name883 *884 * where element_name is885 *886 * IDENT887 *888 * @return Matcher889 */890 public function cssTypeSelector() {891 if ( !isset( $this->cache[__METHOD__] ) ) {892 $this->cache[__METHOD__] = new Juxtaposition( [893 $this->cssOptionalNamespacePrefix(),894 new TokenMatcher( Token::T_IDENT )895 ] );896 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );897 }898 return $this->cache[__METHOD__];899 }900 /**901 * A namespace prefix902 *903 * [ IDENT | '*' ]? '|'904 *905 * @return Matcher906 */907 public function cssNamespacePrefix() {908 if ( !isset( $this->cache[__METHOD__] ) ) {909 $this->cache[__METHOD__] = new Juxtaposition( [910 Quantifier::optional( new Alternative( [911 $this->ident(),912 new DelimMatcher( [ '*' ] ),913 ] ) ),914 new DelimMatcher( [ '|' ] ),915 ] );916 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );917 }918 return $this->cache[__METHOD__];919 }920 /**921 * An optional namespace prefix922 *923 * [ namespace_prefix ]?924 *925 * @return Matcher926 */927 private function cssOptionalNamespacePrefix() {928 if ( !isset( $this->cache[__METHOD__] ) ) {929 $this->cache[__METHOD__] = Quantifier::optional( $this->cssNamespacePrefix() );930 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );931 }932 return $this->cache[__METHOD__];933 }934 /**935 * The universal selector936 *937 * [ namespace_prefix ]? '*'938 *939 * @return Matcher940 */941 public function cssUniversal() {942 if ( !isset( $this->cache[__METHOD__] ) ) {943 $this->cache[__METHOD__] = new Juxtaposition( [944 $this->cssOptionalNamespacePrefix(),945 new DelimMatcher( [ '*' ] )946 ] );947 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );948 }949 return $this->cache[__METHOD__];950 }951 /**952 * An ID selector953 *954 * HASH955 *956 * @return Matcher957 */958 public function cssID() {959 if ( !isset( $this->cache[__METHOD__] ) ) {960 $this->cache[__METHOD__] = new TokenMatcher( Token::T_HASH, function ( Token $t ) {961 return $t->typeFlag() === 'id';962 } );963 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );964 }965 return $this->cache[__METHOD__];966 }967 /**968 * A class selector969 *970 * '.' IDENT971 *972 * @return Matcher973 */974 public function cssClass() {975 if ( !isset( $this->cache[__METHOD__] ) ) {976 $this->cache[__METHOD__] = new Juxtaposition( [977 new DelimMatcher( [ '.' ] ),978 $this->ident()979 ] );980 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );981 }982 return $this->cache[__METHOD__];983 }984 /**985 * An attribute selector986 *987 * '[' S* [ namespace_prefix ]? IDENT S*988 * [ [ PREFIXMATCH |989 * SUFFIXMATCH |990 * SUBSTRINGMATCH |991 * '=' |992 * INCLUDES |993 * DASHMATCH ] S* [ IDENT | STRING ] S*994 * ]? ']'995 *996 * Captures are set for the attribute, test, and value. Note that these997 * captures will probably be relative to the contents of the SimpleBlock998 * that this matcher matches!999 *1000 * @return Matcher1001 */1002 public function cssAttrib() {1003 if ( !isset( $this->cache[__METHOD__] ) ) {1004 // An attribute is going to be parsed by the parser as a1005 // SimpleBlock, so that's what we need to look for here.1006 $this->cache[__METHOD__] = new BlockMatcher( Token::T_LEFT_BRACKET,1007 new Juxtaposition( [1008 $this->optionalWhitespace(),1009 Juxtaposition::create( [1010 $this->cssOptionalNamespacePrefix(),1011 $this->ident(),1012 ] )->capture( 'attribute' ),1013 $this->optionalWhitespace(),1014 Quantifier::optional( new Juxtaposition( [1015 Alternative::create( [1016 new TokenMatcher( Token::T_PREFIX_MATCH ),1017 new TokenMatcher( Token::T_SUFFIX_MATCH ),1018 new TokenMatcher( Token::T_SUBSTRING_MATCH ),1019 new DelimMatcher( [ '=' ] ),1020 new TokenMatcher( Token::T_INCLUDE_MATCH ),1021 new TokenMatcher( Token::T_DASH_MATCH ),1022 ] )->capture( 'test' ),1023 $this->optionalWhitespace(),1024 Alternative::create( [1025 $this->ident(),1026 $this->string(),1027 ] )->capture( 'value' ),1028 $this->optionalWhitespace(),1029 ] ) ),1030 ] )1031 );1032 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );1033 }1034 return $this->cache[__METHOD__];1035 }1036 /**1037 * A pseudo-class or pseudo-element1038 *1039 * ':' ':'? [ IDENT | functional_pseudo ]1040 *1041 * Although this actually only matches the pseudo-selectors defined in the1042 * following sources:1043 * - https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#pseudo-classes1044 * - https://www.w3.org/TR/2016/WD-css-pseudo-4-20160607/1045 *1046 * @return Matcher1047 */1048 public function cssPseudo() {1049 if ( !isset( $this->cache[__METHOD__] ) ) {1050 $colon = new TokenMatcher( Token::T_COLON );1051 $ows = $this->optionalWhitespace();1052 $anplusb = new Juxtaposition( [ $ows, $this->cssANplusB(), $ows ] );1053 $this->cache[__METHOD__] = new Alternative( [1054 new Juxtaposition( [1055 $colon,1056 new Alternative( [1057 new KeywordMatcher( [1058 'link', 'visited', 'hover', 'active', 'focus', 'target', 'enabled', 'disabled', 'checked',1059 'indeterminate', 'root', 'first-child', 'last-child', 'first-of-type',1060 'last-of-type', 'only-child', 'only-of-type', 'empty',1061 // CSS2-compat elements with class syntax1062 'first-line', 'first-letter', 'before', 'after',1063 ] ),1064 new FunctionMatcher( 'lang', new Juxtaposition( [ $ows, $this->ident(), $ows ] ) ),1065 new FunctionMatcher( 'nth-child', $anplusb ),1066 new FunctionMatcher( 'nth-last-child', $anplusb ),1067 new FunctionMatcher( 'nth-of-type', $anplusb ),1068 new FunctionMatcher( 'nth-last-of-type', $anplusb ),1069 ] ),1070 ] ),1071 new Juxtaposition( [1072 $colon,1073 $colon,1074 new KeywordMatcher( [1075 'first-line', 'first-letter', 'before', 'after', 'selection', 'inactive-selection',1076 'spelling-error', 'grammar-error', 'placeholder'1077 ] ),1078 ] ),1079 ] );1080 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );1081 }1082 return $this->cache[__METHOD__];1083 }1084 /**1085 * An "AN+B" form1086 *1087 * https://www.w3.org/TR/2014/CR-css-syntax-3-20140220/#anb1088 *1089 * @return Matcher1090 */1091 public function cssANplusB() {1092 if ( !isset( $this->cache[__METHOD__] ) ) {1093 // Quoth the spec:1094 // > The An+B notation was originally defined using a slightly1095 // > different tokenizer than the rest of CSS, resulting in a1096 // > somewhat odd definition when expressed in terms of CSS tokens.1097 // That's a bit of an understatement1098 $plus = new DelimMatcher( [ '+' ] );1099 $plusQ = Quantifier::optional( new DelimMatcher( [ '+' ] ) );1100 $n = new KeywordMatcher( [ 'n' ] );1101 $dashN = new KeywordMatcher( [ '-n' ] );1102 $nDash = new KeywordMatcher( [ 'n-' ] );1103 $plusQN = new Juxtaposition( [ $plusQ, $n ] );1104 $plusQNDash = new Juxtaposition( [ $plusQ, $nDash ] );1105 $nDimension = new TokenMatcher( Token::T_DIMENSION, function ( Token $t ) {1106 return $t->typeFlag() === 'integer' && !strcasecmp( $t->unit(), 'n' );1107 } );1108 $nDashDimension = new TokenMatcher( Token::T_DIMENSION, function ( Token $t ) {1109 return $t->typeFlag() === 'integer' && !strcasecmp( $t->unit(), 'n-' );1110 } );1111 $nDashDigitDimension = new TokenMatcher( Token::T_DIMENSION, function ( Token $t ) {1112 return $t->typeFlag() === 'integer' && preg_match( '/^n-\d+$/i', $t->unit() );1113 } );1114 $nDashDigitIdent = new TokenMatcher( Token::T_IDENT, function ( Token $t ) {1115 return preg_match( '/^n-\d+$/i', $t->value() );1116 } );1117 $dashNDashDigitIdent = new TokenMatcher( Token::T_IDENT, function ( Token $t ) {1118 return preg_match( '/^-n-\d+$/i', $t->value() );1119 } );1120 $signedInt = new TokenMatcher( Token::T_NUMBER, function ( Token $t ) {1121 return $t->typeFlag() === 'integer' && preg_match( '/^[+-]/', $t->representation() );1122 } );1123 $signlessInt = new TokenMatcher( Token::T_NUMBER, function ( Token $t ) {1124 return $t->typeFlag() === 'integer' && preg_match( '/^\d/', $t->representation() );1125 } );1126 $plusOrMinus = new DelimMatcher( [ '+', '-' ] );1127 $S = $this->optionalWhitespace();1128 $this->cache[__METHOD__] = new Alternative( [1129 new KeywordMatcher( [ 'odd', 'even' ] ),1130 new TokenMatcher( Token::T_NUMBER, function ( Token $t ) {1131 return $t->typeFlag() === 'integer';1132 } ),1133 $nDimension,1134 $plusQN,1135 $dashN,1136 $nDashDigitDimension,1137 new Juxtaposition( [ $plusQ, $nDashDigitIdent ] ),1138 $dashNDashDigitIdent,1139 new Juxtaposition( [ $nDimension, $S, $signedInt ] ),1140 new Juxtaposition( [ $plusQN, $S, $signedInt ] ),1141 new Juxtaposition( [ $dashN, $S, $signedInt ] ),1142 new Juxtaposition( [ $nDashDimension, $S, $signlessInt ] ),1143 new Juxtaposition( [ $plusQNDash, $S, $signlessInt ] ),1144 new Juxtaposition( [ new KeywordMatcher( [ '-n-' ] ), $S, $signlessInt ] ),1145 new Juxtaposition( [ $nDimension, $S, $plusOrMinus, $S, $signlessInt ] ),1146 new Juxtaposition( [ $plusQN, $S, $plusOrMinus, $S, $signlessInt ] ),1147 new Juxtaposition( [ $dashN, $S, $plusOrMinus, $S, $signlessInt ] )1148 ] );1149 $this->cache[__METHOD__]->setDefaultOptions( [ 'skip-whitespace' => false ] );1150 }1151 return $this->cache[__METHOD__];1152 }1153 /**1154 * A negation1155 *1156 * ':' not( S* [ type_selector | universal | HASH | class | attrib | pseudo ] S* ')'1157 *1158 * @return Matcher1159 */1160 public function cssNegation() {1161 if ( !isset( $this->cache[__METHOD__] ) ) {1162 // A negation is going to be parsed by the parser as a colon1163 // followed by a CSSFunction, so that's what we need to look for1164 // here.1165 $this->cache[__METHOD__] = new Juxtaposition( [1166 new TokenMatcher( Token::T_COLON ),1167 new FunctionMatcher( 'not',1168 new Juxtaposition( [1169 $this->optionalWhitespace(),1170 new Alternative( [1171 $this->cssTypeSelector(),1172 $this->cssUniversal(),1173 $this->cssID(),1174 $this->cssClass(),1175 $this->cssAttrib(),1176 $this->cssPseudo(),1177 ] ),1178 $this->optionalWhitespace(),1179 ] )1180 )...

Full Screen

Full Screen

Parser.php

Source:Parser.php Github

copy

Full Screen

...22 */23 public function parse(string $json): void24 {25 $buffer = Unicode\CharBufferFactory::createFromString($json);26 $lexer = new Lexer\TokenReader($buffer, $this->getTokenMatcher(), $this->getTokenFactory());27 $parser = new LL1\Parser($this->getGrammar(), $lexer, $this->getTranslator());28 try {29 $parser->run();30 } catch (\Throwable $e) {31 throw new Exception("Failed to parse JSON", 0, $e);32 }33 }34 /**35 * @return ContextFree\Grammar36 * @throws Exception37 */38 private function getGrammar(): ContextFree\Grammar39 {40 if (!isset($this->grammar)) {41 try {42 $this->grammar = ContextFree\GrammarLoader::loadFile(__DIR__ . "/../spec/GrammarSpec.php");43 } catch (\Throwable $e) {44 throw new Exception("Failed to load JSON grammar specification", 0, $e);45 }46 }47 return $this->grammar;48 }49 private function getTokenMatcher(): Lexer\TokenMatcherInterface50 {51 if (!isset($this->tokenMatcher)) {52 $this->tokenMatcher = new TokenMatcher;53 }54 return $this->tokenMatcher;55 }56 /**57 * @return Lexer\TokenFactoryInterface58 * @throws Exception59 */60 private function getTokenFactory(): Lexer\TokenFactoryInterface61 {62 if (!isset($this->tokenFactory)) {63 $this->tokenFactory = new ContextFree\TokenFactory($this->getGrammar());64 }65 return $this->tokenFactory;66 }...

Full Screen

Full Screen

TemplateStylesFontFaceAtRuleSanitizer.php

Source:TemplateStylesFontFaceAtRuleSanitizer.php Github

copy

Full Screen

...6use Wikimedia\CSS\Grammar\Alternative;7use Wikimedia\CSS\Grammar\Juxtaposition;8use Wikimedia\CSS\Grammar\MatcherFactory;9use Wikimedia\CSS\Grammar\Quantifier;10use Wikimedia\CSS\Grammar\TokenMatcher;11use Wikimedia\CSS\Objects\Token;12use Wikimedia\CSS\Sanitizer\FontFaceAtRuleSanitizer;13/**14 * Extend the standard `@font-face` matcher to require a prefix on families.15 */16class TemplateStylesFontFaceAtRuleSanitizer extends FontFaceAtRuleSanitizer {17 /**18 * @param MatcherFactory $matcherFactory19 */20 public function __construct( MatcherFactory $matcherFactory ) {21 parent::__construct( $matcherFactory );22 // Only allow the font-family if it begins with "TemplateStyles"23 $this->propertySanitizer->setKnownProperties( [24 'font-family' => new Alternative( [25 new TokenMatcher( Token::T_STRING, function ( Token $t ) {26 return substr( $t->value(), 0, 14 ) === 'TemplateStyles';27 } ),28 new Juxtaposition( [29 new TokenMatcher( Token::T_IDENT, function ( Token $t ) {30 return substr( $t->value(), 0, 14 ) === 'TemplateStyles';31 } ),32 Quantifier::star( $matcherFactory->ident() ),33 ] ),34 ] ),35 ] + $this->propertySanitizer->getKnownProperties() );36 }37}...

Full Screen

Full Screen

TokenMatcher

Using AI Code Generation

copy

Full Screen

1require_once 'vendor/autoload.php';2use Behat\Gherkin\TokenMatcher;3use Behat\Gherkin\Keywords\KeywordsInterface;4use Behat\Gherkin\Keywords\ArrayKeywords;5use Behat\Gherkin\Token;6use Behat\Gherkin\Lexer;7use Behat\Gherkin\Parser;8use Behat\Gherkin\Node\ScenarioNode;9use Behat\Gherkin\Node\FeatureNode;10$keywords = new ArrayKeywords(array(11 'en' => array(12));13$lexer = new Lexer($keywords);14$parser = new Parser($keywords);15$feature = $parser->parse(16 $lexer->tokenize($featureText)17);18$feature->getFeature();19$feature->getDescription();20$feature->getTags();21$feature->getBackground();22$feature->getScenarios();23$scenario = $feature->getScenarios()[0];24$scenario->getTitle();25$scenario->getTags();26$scenario->getSteps();27$step = $scenario->getSteps()[0];28$step->getType();29$step->getText();30$step->getArguments();31$argument = $step->getArguments()[0];32$argument->getKeyword();33$argument->getRows();34$row = $argument->getRows()[0];35$row->getCells();36$cell = $row->getCells()[0];37$cell->getValue();38$keywords = $lexer->getKeywords();39$keywords->getKeywords();40$keywords->getKeyword('given');41$keywords->getKeywordType('Given');42$keywords->hasKeyword('given');43$keywords->hasKeywordType('Given');44$token = new Token(0, 'Given', 1);45$token->getLine();46$token->getRaw();47$token->getTrimmed();48$token->getIndent();49$token->getColumn();

Full Screen

Full Screen

TokenMatcher

Using AI Code Generation

copy

Full Screen

1require_once 'vendor/autoload.php';2use Behat\Gherkin\TokenMatcher;3use Behat\Gherkin\Lexer;4use Behat\Gherkin\Parser;5use Behat\Gherkin\Keywords\ArrayKeywords;6use Behat\Gherkin\Keywords\KeywordsInterface;7use Behat\Gherkin\Keywords\Keywords;8use Behat\Gherkin\Keywords\KeywordsArray;9$keywords = new KeywordsArray(array(10 'en' => array(11));12$lexer = new Lexer($keywords);13$parser = new Parser($lexer);14$feature = $parser->parse(file_get_contents('1.feature'));15$tokenMatcher = new TokenMatcher();16$tokens = $lexer->tokenize(file_get_contents('1.feature'));17foreach ($tokens as $token) {18 if ($tokenMatcher->isGivenKeyword($token)) {19 print $token->getLine()." ".$token->getKeyword()."20";21 }22}

Full Screen

Full Screen

TokenMatcher

Using AI Code Generation

copy

Full Screen

1$tokenMatcher = new \Behat\Gherkin\TokenMatcher();2$tokenMatcher->isStepKeyword("Given");3$tokenMatcher = new \Behat\Gherkin\TokenMatcher();4$tokenMatcher->isStepKeyword("Given");5$tokenMatcher = new \Behat\Gherkin\TokenMatcher();6$tokenMatcher->isStepKeyword("Given");7$tokenMatcher = new \Behat\Gherkin\TokenMatcher();8$tokenMatcher->isStepKeyword("Given");9$tokenMatcher = new \Behat\Gherkin\TokenMatcher();10$tokenMatcher->isStepKeyword("Given");11$tokenMatcher = new \Behat\Gherkin\TokenMatcher();12$tokenMatcher->isStepKeyword("Given");13unset($tokenMatcher::$keywords);

Full Screen

Full Screen

TokenMatcher

Using AI Code Generation

copy

Full Screen

1$gherkin = new \Behat\Gherkin\Gherkin();2$gherkin->registerLanguage('en', new \Behat\Gherkin\Language('en', 'en', array()));3$parser = new \Behat\Gherkin\Parser($gherkin);4$features = $parser->parse(file_get_contents('features/1.feature'));5$feature = $features[0];6$scenario = $feature->getScenarios()[0];7$steps = $scenario->getSteps();8$keywords = array();9foreach ($steps as $step) {10 $keywords[] = $step->getKeyword();11}12echo json_encode($keywords);13$gherkin = new \Behat\Gherkin\Gherkin();14$gherkin->registerLanguage('en', new \Behat\Gherkin\Language('en', 'en', array()));15$parser = new \Behat\Gherkin\Parser($gherkin);16$features = $parser->parse(file_get_contents('features/2.feature'));17$feature = $features[0];18$scenario = $feature->getScenarios()[0];19$steps = $scenario->getSteps();20$keywords = array();21foreach ($steps as $step) {22 $keywords[] = $step->getKeyword();23}24echo json_encode($keywords);25$gherkin = new \Behat\Gherkin\Gherkin();26$gherkin->registerLanguage('en', new \Behat\Gherkin\Language('en', 'en', array()));27$parser = new \Behat\Gherkin\Parser($gherkin);28$features = $parser->parse(file_get_contents('features/3.feature'));29$feature = $features[0];30$scenario = $feature->getScenarios()[0];31$steps = $scenario->getSteps();32$keywords = array();33foreach ($steps as $step) {34 $keywords[] = $step->getKeyword();35}36echo json_encode($keywords);37$gherkin = new \Behat\Gherkin\Gherkin();

Full Screen

Full Screen

TokenMatcher

Using AI Code Generation

copy

Full Screen

1$gherkin = new Gherkin\Gherkin();2$parser = $gherkin->getParser();3$matcher = new Gherkin\TokenMatcher();4$parser->match($matcher->EOF(), array(new Gherkin\Token('EOF', '')));5$gherkin = new Gherkin\Gherkin();6$parser = $gherkin->getParser();7$ast = $parser->parse($text);8$visitor = new MyVisitor();9$visitor->visit($ast);10Fatal error: Uncaught exception 'LogicException' with message 'Method visitFeature() must be defined in class MyVisitor' in C:\xampp\htdocs\gherkin\vendor\behat\gherkin\src\Gherkin\Ast\Visitor\AstNodeVisitor.php on line 5611$gherkin = new Gherkin\Gherkin();12$parser = $gherkin->getParser();

Full Screen

Full Screen

TokenMatcher

Using AI Code Generation

copy

Full Screen

1require_once 'vendor/autoload.php';2use Behat\Gherkin\TokenMatcher\TokenMatcher;3$matcher = new TokenMatcher();4echo $matcher->match('Given', 'Given');5echo $matcher->match('Given', 'When');6echo $matcher->match('Given', 'Then');7echo $matcher->match('When', 'When');8echo $matcher->match('When', 'Then');9echo $matcher->match('Then', 'Then');10echo $matcher->match('Then', 'Given');11echo $matcher->match('And', 'And');12echo $matcher->match('And', 'When');13echo $matcher->match('And', 'Then');14echo $matcher->match('But', 'But');15echo $matcher->match('But', 'When');16echo $matcher->match('But', 'Then');

Full Screen

Full Screen

TokenMatcher

Using AI Code Generation

copy

Full Screen

1$lexer = new Lexer();2$parser = new Parser($lexer);3$token_matcher = new TokenMatcher();4$token_matcher->isGivenTableNode($parser->parse($feature));5$lexer = new Lexer();6$parser = new Parser($lexer);7$token = new Token();8$token->isGivenTableNode($parser->parse($feature));

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Gherkin-php automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Run Selenium Automation Tests on LambdaTest Cloud Grid

Trigger Selenium automation tests on a cloud-based Grid of 3000+ real browsers and operating systems.

Test now for Free

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful