How to match colon in sweet.js? - sweet.js

macro m {
rule {
$a: $b
} => {
$a($b)
}
}
m 1: 2
I think sweetjs is interpreting the colon as a marker for match class. If so, how do I escape that make make sweetjs match it as it is?
This seems to work just fine though
macro m {
rule {
:$b
} => {
$b
}
}
m :1

You can use $[:] to match a literal.

Related

Regex expected to match one letter matches whole word [duplicate]

This question already has answers here:
Regular expression pipe confusion
(5 answers)
Closed 5 months ago.
I have this expression in a switch statement for a script controlpanel
$ctrlinpt=read-host ">>>"
switch -regex ( $ctrlinpt )
{
<#1#>'^\w{2,}|\d{2,}$' { do this }
<#2#>'^c{1}|C{1}$' { do that }
<#3#>'^l{1}|L{1}$' { do somethign else }
<#4#>'^s{1}|S{1}$' { take a break }
<#5#>'^exit$'{ go home }
}
The first condition should match any input with more than one character and it does. However , if the input starts with one of the letters in the other conditions, it also matches their cases
for example
"Task1" matches only case 1
"Legacy" matches case 1 and case 3
"supper" matches case 1 and case 4
I expect cases 2,3, and 4 to only match an input of exactly the one character stated. What am I doing wrong?
The pattern '^l{1}|L{1}$' is interpreted as "a string starting with l OR a string ending with L" - and since PowerShell does case-insensitive comparisons by default, "a string starting with l" perfectly describes Legacy.
To fix this, you can nest the alternation in a grouping construct:
^(?:l{1}|L{1})$
... or use a character class:
^[lL]$
... or, since the matches are case-insensitive by default anyway, simply match on a single character literal:
^l$
Thus, your switch becomes:
$ctrlinpt = read-host ">>>"
switch -regex ( $ctrlinpt ) {
'^(?:\w{2,}|\d{2,})$' { do this }
'^c$' { do that }
'^l$' { do somethign else }
'^s$' { take a break }
'^exit$' { go home }
}
Since regex isn't really required for the last 4 cases, I'd suggest removing the -regex mode switch altogether and use a predicate for the first case instead:
$ctrlinpt = read-host ">>>"
switch ( $ctrlinpt ) {
{ $_ -match '^(?:\w{2,}|\d{2,})$' } { do this }
'c' { do that }
'l' { do somethign else }
's' { take a break }
'exit' { go home }
}

How to check is Jenkins pram contains a character

I am trying to check if my Jenkins parameter contains a hostname.
But when I use Regular Expressions to see if it contains the name it doesn't check.
I would guess I have an error in the way I am checking or how I have it wrapped in brackets.
Below is a sample of what I am working with
stage('Release 1') {
when {
expression { params.SECRET_NAME != "" && params.STAGING_ENV != ("*some.host.name*") }
}
steps {
echo "Release 1"
}
}
stage('Release 2') {
when {
expression {params.STAGING_ENV == ("*some.host.name*") && params.SECRET_NAME == ("*+*") }
}
steps {
echo "Release 2"
}
}
}
I want it to skip the stage in my Jenkins pipeline if it does not meet the conditions
Ok, you need multiple changes here, from inside out:
Replace the * with .*. Simply put, in regex * denotes the same (set) of characters any number of times (abc* matches abccccc), whereas .* denotes any character any number of times (abc.* matches abccccc, abcdefg, abcadkhsdalksd, etc.).
Remove the double quotes " surrounding the regex patterns; lest you want them to be interpreted as string literals.
Wrap the regex patterns within delimiters, usually / to define the string boundary.
The brackets () themselves are optional here.
To match regular expressions, replace the equal operator == with the match operator ==~ (strict), which returns a boolean.
There is no "NOT match" operator in Groovy. To invert the match, you need to invert the result of the entire expression.
If the + in *+*should be a literal, then you must escape it as *\+*.
Stitching these together, your pipeline should look like:
stage('Release 1') {
when {
expression {
params.SECRET_NAME != "" && !(params.STAGING_ENV ==~ /.*some.host.name.*/)
}
}
steps {
echo "Release 1"
}
}
stage('Release 2') {
when {
expression {
params.STAGING_ENV ==~ /.*some.host.name.*/ && params.SECRET_NAME ==~ /.*\+.*/
}
}
steps {
echo "Release 2"
}
}
Further reading:
http://docs.groovy-lang.org/latest/html/documentation/core-operators.html
http://web.mit.edu/hackl/www/lab/turkshop/slides/regex-cheatsheet.pdf

Perl6 grammar and action error : "Cannot find method 'ann' on object of type NQPMu"

Okay, I am still having trouble with perl6 grammar and action. I want to find a pattern in a string, and as soon as it is is found, change the pattern according to action, and return the modified string.
my $test = "xx, 1-March-23, 23.feb.21, yy foo 12/january/2099 , zzz";
# want this result: xx, 010323, 230221, yy foo 120199 , zzz";
# 2 digits for day, month, year
grammar month {
regex TOP { <unit>+ }
regex unit { <before> <form1> <after> }
regex before { .*? }
regex after { .*? }
regex form1 { \s* <dd> <slash> <mon> <slash> <yy> \s* }
regex slash { \s* <[ \- \/ \. ]> \s* }
regex dd { \d ** 1..2 }
regex yy { (19 | 20)? \d\d }
proto regex mon {*}
regex mon:sym<jan> { \w 'an' \w* }
regex mon:sym<feb> { <sym> }
regex mon:sym<mar> { <[Mm]> 'ar' \w* }
}
class monAct {
method TOP ($/) { make $<unit>.map({.made}); }
method unit ($/) { make $<before> ~ $<form1>.made ~$<after>; }
method form1 ($/) { make $<dd>.made ~ $<mon>.made ~ $<yy>; }
method dd ($/) {
my $ddStr = $/.Str;
if $ddStr.chars == 1 { make "0" ~ $ddStr; } else { make $ddStr; }
}
method mon:sym<jan> ($/) { make "01"; };
method mon:sym<feb> ($/) { make "02"; };
method mon:sym<mar> ($/) { make "03"; };
}
my $m = month.parse($test, actions => monAct.new);
say $m;
say $m.made;
But it says:
===SORRY!===Cannot find method 'ann' on object of type NQPMu
What did I do wrong ? Thank you for your help !!!
This looks like a bug in Rakudo to me, possibly related to before being part of the syntax for lookahead assertions.
It can already be triggered with a simple / <before> /:
$ perl6 --version
This is Rakudo version 2016.11-20-gbd42363 built on MoarVM version 2016.11-10-g0132729
implementing Perl 6.c.
$ perl6 -e '/ <before> /'
===SORRY!===
Cannot find method 'ann' on object of type NQPMu
At the very least, it's a case of a less than awesome error message.
You should report this to rakudobug#perl.org, cf
How to report a bug.

Map strange behaviour

I have a map function as follows, which reads from an array of lines generated by a unix command.
my %versions = map {
if (m/(?|(?:^Patch\s(?(?=description).*?(\w+)\sPATCH).*?(\d+(?:\.\d+)+).*)|(?:^(OPatch)\s(?=version).*?(\d+(\.\d+)+)))/)
{ 'hello' => 'bye'; }
} #dbnode_versions;
print Dumper(\%versions); gives
$VAR1 = {
'' => undef,
'hello' => 'bye',
'bye' => ''
};
which I find extremely odd, as the hello and bye values should only get added if the regex is true. Anyone able to help me out?
Well, you have to consider what happens when the regex doesn't match, and the if is false. The if will evaluate to some value, although you shouldn't rely on the value of a statement.
Especially, if (cond) { expression } is roughly equivalent to cond and expression. This means that if the regex (our cond) will not match, we'll get a false value.
use Data::Dump;
dd [map { /foo(bar)/ and (hello => 'bye') } qw/foo foobar bar/];
What is your expected output? You may have thought ["hello", "bye"]. But actually, we get
["", "hello", "bye", ""]
because "" represents the false value returned by the regex match on failure.
If you want to return nothing in failure cases, you should explicitly return an empty list:
map { /foo(bar)/ ? (hello => 'bye') : () } qw/foo foobar bar/
or use grep, which filters a list for those elements that match a condition:
my %hash =
map { hello => 'bye' } # replace each matching element
grep { /foo(bar)/ } # filter for matching elements
qw/foo foobar bar/;
The %hash will them either be () or (hello => 'bye'), as each key can only occur once.

How to match the variable in switch with contents of a list?

I have a doubt concerning the use of switch in tcl. Mainly, I was wondering if it was possible to make something like:
switch myvar {
list1 {
puts "myvar matches contents of list1"; }
list2 {
puts "myvar matches contents of list2"; }
default {
puts "myvar doesn't match any content of any list"; }
}
In here, list1 and list2 would be either a list or array of strings containing the names of different files.
Is this even possible without making a very detailed regexp search?
Thanks!
You can rewrite it as an if elseif else construct easily, as Brian Fenton already said (and simplify it with the 'in' operator too.
if {$myvar in $list1} {
puts "myvar matches content of list"
} elseif {$myvar in $list2} {
puts "myvar matches content of list2"
} elseif {
puts "myvar doesn't match any content of any list"
}
You could of course wrap up the code and write your own switch version that does what you want, after all, this is Tcl...
proc listswitch {item conditions} {
if {[llength $conditions] % 2} {
return -code error "Conditions must be pairs"
}
set code ""
foreach {cond block} $conditions {
if {$cond eq "default"} {
set code $block
break
} elseif {$item in $cond} {
set code $block
break
}
}
if {$code ne ""} {
uplevel 1 $code
}
}
listswitch 10 {
{10 20 30 50} {
puts "Match in list 1" }
{50 20 90 11} {
puts "Match in list 2"
}
default {
puts "No match"
}
}
You need to worry a little if you want to match filenames literally, or what kind of equality your interested in though. There are some subtle things there, like case insensitive filesystems, different directory separators, absolute vs. relative and even stuff like filesystem encodings which might change the outcome.
Nice question Jason. At first, I thought you wanted a way to compare the contents of two lists. But I think you want to check if the string is a member of the lists. I don't see any easy way to do that with switch, so what I would do is very simply to use lsearch.
if {[lsearch $list1 $myvar ] != -1} {
puts "myvar matches contents of list1"; }
} elseif {[lsearch $list2 $myvar ] != -1} {
puts "myvar matches contents of list2"; }
} else
puts "myvar doesn't match any content of any list"; }
}