ReSharper Formatting Ternary Operator in C# - c#

This is driving me up the wall now. The ternary formatting options in ReSharper -> Options -> C# do not cover indentation, just spacing of '?' and ':' characters, and line chopping.
What I want is:
var x = expr1
? expr2
: expr3;
But what I get is:
var x = expr1
? expr2
: expr3;
If the ternary operator formatting was offering no assistance, I thought that the Chained binary expressions may help, but no. That is set as follows.
var a = someOperand + operand2
+ operand3
+ operand4;
Any ideas?

Try enabling ReSharper | Options | Code Editing | C# | Formatting Style | Other | Align Multiline Constructs | Expression

Related

ANTLR4 grammar integration complexities for selection with removals

I’m attempting to create a grammar for a lighting control system and I make good progress when testing with the tree gui tool but it all seems to fall apart when I attempt to implement it into my app.
The basic structure of the language is [Source] [Mask] [Command] [Destination]. Mask is optional so a super simple sample input might look like this : Fixture 1 # 50 which bypasses Mask. Fixture 1 is the source, # is the command and 50 is the destination which in this case is an intensity value.
I’ve no issues with this type of input but things get complicated as I try and build out more complex source selection. Let’s say I want to select a range of fixtures and remove a few from the selection and then add more fixtures after.
Fixture 1 Thru 50 – 25 – 30 – 35 + 40 > 45 # 50
This is a very common syntax on existing control systems but I’m stumped at how to design the grammar for this in a way that makes integration into my app not too painful.
The user could just as easily type the following:
1 Thru 50 – 25 – 30 – 35 + 40 > 45 # 50
Because sourceType (fixture) is not provided, its inferred.
To try and deal with the above situations, I've written the following:
grammar LiteMic;
/*
* Parser Rules
*/
start : expression;
expression : source command destination
| source mask command destination
| command destination
| source command;
destination : sourceType number
| sourceType number sourceType number
| number;
command : COMMAND;
mask : SOURCETYPE;
operator : ADD #Add
| SUB #Subtract
;
plus : ADD;
minus : SUB;
source : singleSource (plus source)*
| rangeSource (plus source)*
;
singleSource : sourceType number #SourceWithType
| number #InferedSource
;
rangeSource : sourceRange (removeSource)*
;
sourceRange : singleSource '>' singleSource;
removeSource : '-' source;
sourceType : SOURCETYPE;
number : NUMBER;
compileUnit
: EOF
;
/*
* Lexer Rules
*/
SOURCETYPE : 'Cue'
| 'Playback'
| 'List'
| 'Intensity'
| 'Position'
| 'Colour'
| 'Beam'
| 'Effect'
| 'Group'
| 'Fixture'
;
COMMAND : '#'
| 'Record'
| 'Update'
| 'Copy'
| 'Move'
| 'Delete'
| 'Highlight'
| 'Full'
;
ADD : '+' ;
SUB : '-' ;
THRU : '>' ;
/* A number: can be an integer value, or a decimal value */
NUMBER : [0-9]+ ;
/* We're going to ignore all white space characters */
WS : [ \t\r\n]+ -> skip
;
Running the command against grun gui produces the following:
I've had some measure of success being able to override the Listener for AddRangeSource as I can loop through and add the correct types but it all falls apart when I try and remove a range.
1 > 50 - 30 > 35 # 50
This produces a problem as the removal of a range matches to the 'addRangeSource'.
I'm pretty sure I'm missing something obvious and I've been working my way through the book I bought on Amazon but it's still not cleared up in my head how to archieve what I'm after and I've been looking at this for a week.
For good measure, below is a tree for a more advanced query that seems ok apart from the selection.
Does anyone have any pointers / suggestions on where I'm going wrong?
Cheers,
Mike
You can solve the problem by reorganizing the grammar a little:
Merge rangeSource with sourceRange:
rangeSource : singleSource '>' singleSource;
Note: This rule also matches input like Beam 1 > Group 16, which might be unintended, in that case you could use this:
rangeSource : sourceType? number '>' number;
Rename source to sourceList (and don't forget to change it in the expression rule):
expression : sourceList command destination
| sourceList mask command destination
| command destination
| sourceList command;
Add a source rule that matches either singleSource or rangeSource:
source : singleSource | rangeSource;
Put + and - at the same level (as addSource and removeSource):
addSource : plus source;
removeSource : minus source;
Change sourceList to accept a list of addSource/removeSource:
sourceList : source (addSource|removeSource)*;
I tried this and it doesn't have any problems with parsing even the more advanced query.

How to extract specific value from a string with Regex? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am new to Regex and i want to extract a specific value from a string, i have strings like:
"20098: Blue Quest"
"95: Internal Comp"
"33: ICE"
and so on.Every string has the same pattern : Number followed by ":" followed by a space and random text. I want to get the numbers at the start for ex: "20098","95","33" etc.
i tried
Regex ex = new regex(#"[0-9]+\: [a-zA-Z]$")
This is not giving me any solution, Where am i going wrong?
(i am using c#)
This is a totally silly solution. However, i decided to benchmark an unchecked pointer version, against the other regex and int parse solutions here in the answers.
You mentioned the strings are always the same format, so i decided to see how fast we could get it.
Yehaa
public unsafe static int? FindInt(string val)
{
var result = 0;
fixed (char* p = val)
{
for (var i = 0; i < val.Length; i++)
{
if (*p == ':')return result;
result = result * 10 + *p - 48;
}
return null;
}
}
I run each test 50 times with 100,000 comparisons, and 1,000,000 respectively with both Lee Gunn's int.parse,The fourth bird version ^\d+(?=: [A-Z]) also my pointer version and ^\d+
Results
Test Framework : .NET Framework 4.7.1
Scale : 100000
Name | Time | Delta | Deviation | Cycles
----------------------------------------------------------------------------
Pointers | 2.597 ms | 0.144 ms | 0.19 | 8,836,015
Int.Parse | 17.111 ms | 1.009 ms | 2.91 | 57,167,918
Regex ^\d+ | 85.564 ms | 10.957 ms | 6.14 | 290,724,120
Regex ^\d+(?=: [A-Z]) | 98.912 ms | 1.508 ms | 7.16 | 336,716,453
Scale : 1000000
Name | Time | Delta | Deviation | Cycles
-------------------------------------------------------------------------------
Pointers | 25.968 ms | 1.150 ms | 1.15 | 88,395,856
Int.Parse | 143.382 ms | 2.536 ms | 2.62 | 487,929,382
Regex ^\d+ | 847.109 ms | 14.375 ms | 21.92 | 2,880,964,856
Regex ^\d+(?=: [A-Z]) | 950.591 ms | 6.281 ms | 20.38 | 3,235,489,411
Not surprisingly regex sucks
If they are all separate strings - you don't need to use a regex, you can simply use:
var s = "20098: Blue Quest";
var index = s.IndexOf(':');
if(index > 0){
if(int.TryParse(s.Substring(0, index), out var number))
{
// Do stuff
}
}
If they're all contained in one sting, you can loop over each line and perform the Substring. Perhaps a bit easier to read as a lot of people aren't comfortable with regular expressions.
In your regex "[0-9]+: [a-zA-Z]$ you match one or more digits followed by a colon and then a single lower or uppercase character.
That would match 20098: B and would not match the digits only.
There are better alternatives besides using a regex like as suggested, but you might match from the beginning of the string ^ one or more digits \d+ and use a positive lookahead (?= to assert that what follows is a colon, whitespace and an uppercase character [A-Z])
^\d+(?=: [A-Z])
Firstly, after colon, yoiu should use \s instead of literal space. Also, if the text after colon can include spaces, the second group should also allow /s and have a + after it.
[0-9]+\:\s[a-zA-Z\s]+$
Secondly, that entire regex will return the entire string. If you only want the first number, then the regex would be simply:
[0-9]+
You can use look-behind ?<= to find any number following ^" (where ^ is the beginning of line):
(?<=^")[0-9]+

How do I validate a decimal like this 00.00?

I am learning validation expressions and have attempted to write one to check a decimal like the example below but I am having some issues.
The number to validate is like this:
00.00 (any 2 numbers, then a ., then any 2 numbers)
This is what I have:
^[0-9]{2}[.][0-9]{2}$
This expression returns false but from a tutorial I read I was under the understanding that it should be written like this:
^ = starting character
[0-9] = any number 0-9
{2} = 2 numbers 0-9
[.] = full stop
$ = end
Use the right tool for the job. If you're parsing decimals, use decimal.TryParse instead of Regex.
string input = "00.00";
decimal d;
var parsed = Decimal.TryParse(input, out d);
If the requirement is to always have a 2 digits then a decimal point then 2 digits you could do:
var lessThan100 = d < 100m;
var twoDecimals = d % 0.01m == 0;
var allOkay = parsed && lessThan100 && twoDecimals;
So our results are
Stage | input = "" | "abc" | "00.00" | "123" | "0.1234"
-------------------------------------------------------------
parsed | false | false | true | true | true
lessThan100 | - | - | true | false | true
twoDecimals | - | - | true | - | false
Although if you really need it to be that exact format then you could do
var separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
var allOkay = isOkay && input.Length == 5 && input[2] == separator;
If you absolutely have to use Regex then the following works as required:
Regex.IsMatch("12.34", #"^([0-9]{2}\.[0-9]{2})$")
Regex explanation:
^ - start of string
() - match what's inside of brackets
[0-9]{2} exactly 2 characters in the range 0 - 9
\. - full stop (escaped)
$ - end of string

traversing an ast having complex conditional expression to generate linq expression

I'm using Irony.net for generating a parse tree out of the source. Essentially I'm using ExpressionEvaluatorGrammer like grammer for binary expressions (arithmetic, relational and logical/conditional). I want to convert the resultant parse tree into Linq expression by traversing it. However, the tree does not seem to have a formation directly convertable to linq conditional expression. Hypothetical example of such an expression:
1 == 1 && 4 - 1 == 3
generates (pseudo xml tree for brevity):
<binary>
<binary>
<binary>
<literal>1</literal>
<op>==</op>
<literal>1</literal>
</binary>
<op>&&</op>
<binary>
<literal>4</literal>
<op>-</op>
<literal>1</literal>
</binary>
</binary>
<op>==</op>
<literal>3</literal>
</binary>
In the tree above, the arithmetic expression (4 - 1) becomes the right expression to the && logical operation as the parent node closes after it. In the ideal world, it should have been a left expression of the nodes representing "== 3".
How do you traverse such a tree to generate a proper and operation? Or, is there a way to generate the tree in the form I desire?
Edit: here's the grammer (partial) definition. I have taken it from ExpressionEvaluatorGrammer that comes with Irony.interpreter.
RegisterOperators(15, "&", "&&", "|", "||");
RegisterOperators(20, "==", "<", "<=", ">", ">=", "!=");
RegisterOperators(30, "+", "-");
RegisterOperators(40, "*", "/");
Expr.Rule = Term
Term.Rule = number | ParExpr | stringLit | FunctionCall | identifier | MemberAccess | IndexedAccess;
ParExpr.Rule = "(" + Expr + ")";
BinExpr.Rule = Expr + BinOp + Expr;
BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**" | "==" | "<" | "<=" | ">" | ">=" | "!=" | "&&" | "||" | "&" | "|";
You cannot fix this by traversing the tree in a magical/special way. Your parser is incorrect! Probably, it is just misconfigured. You absolutely need to get the correct tree from it in order to process it further.
Probably you have wrong operator precedence rules in it. It looks like it, at least. Try adding parenthesis to see if it fixed up the tree.
Assuming the operator precedence is correct, you should walk the tree recursively using the Visitor Pattern, returning an Expression at each level:
XName xBinary = "binary";
XName xLiteral = "literal";
Expression Visit(XElement elt)
{
if (elt.Name == xBinary)
{
return VisitBinary(elt);
}
else if (elt.Name == xLiteral)
{
return VisitLiteral(elt);
} // ...
throw new NotSupportedException();
}
Now that you have the Visit structure, you simply write each specific visitor to use your main Visit:
Expression VisitLiteral(XElement elt)
{
Debug.Assert(elt.Name == xLiteral);
return Expression.Constant((int)elt);
}
Expression VisitBinary(XElement elt)
{
Debug.Assert(elt.Name == xBinary);
Debug.Assert(elt.Elements().Count() >= 3);
var lhs = elt.Elements().ElementAt(0);
var op = elt.Elements().ElementAt(1);
var rhs = elt.Elements().ElementAt(2);
switch((string)op)
{
case "+":
// by chaining LHS and RHS to Visit we allow the tree to be constructed
// properly as Visit performs the per-element dispatch
return Expression.Add(Visit(lhs), Visit(rhs));
case "&&":
return Expression.AndAlso(Visit(lhs), Visit(rhs));
default:
throw new NotSupportedException();
}
}

Can you improve this 'lines of code algorithm' in F#?

I've written a little script to iterate across files in folders to count lines of code.
The heart of the script is this function to count lines of whitespace, comments, and code. (Note that for the moment it is tailored to C# and doesn't know about multi-line comments).
It just doesn't look very nice to me - has anyone got a cleaner version?
// from list of strings return tuple with count of (whitespace, comments, code)
let loc (arr:List<string>) =
let innerloc (whitesp, comment, code) (l:string) =
let s = l.Trim([|' ';'\t'|]) // remove leading whitespace
match s with
| "" -> (whitesp + 1, comment, code) //blank lines
| "{" -> (whitesp + 1, comment, code) //opening blocks
| "}" -> (whitesp + 1, comment, code) //closing blocks
| _ when s.StartsWith("#") -> (whitesp + 1, comment, code) //regions
| _ when s.StartsWith("//") -> (whitesp, comment + 1, code) //comments
| _ -> (whitesp, comment, code + 1)
List.fold_left innerloc (0,0,0) arr
I think what you have is fine, but here's some variety to mix it up. (This solution repeats your problem of ignoring trailing whitespace.)
type Line =
| Whitespace = 0
| Comment = 1
| Code = 2
let Classify (l:string) =
let s = l.TrimStart([|' ';'\t'|])
match s with
| "" | "{" | "}" -> Line.Whitespace
| _ when s.StartsWith("#") -> Line.Whitespace
| _ when s.StartsWith("//") -> Line.Comment
| _ -> Line.Code
let Loc (arr:list<_>) =
let sums = Array.create 3 0
arr
|> List.iter (fun line ->
let i = Classify line |> int
sums.[i] <- sums.[i] + 1)
sums
"Classify" as a separate entity might be useful in another context.
A better site for this might be refactormycode - it's tailored exactly for these questions.
Can't see much wrong with that other than the fact you will count a single brace with trailing spaces as code instead of whitespace.

Categories

Resources