Formatting math expression before parsing using math_expressions package in Flutter - flutter

How to properly format a math expression before passing it to the math_expressions package in flutter?
Context
I'm using math_expressions package but there are two cases I found when it throws an error:
A. Missing an asterisk before a parenthesis.
B. Missing parenthesis within the expression.
E.g.
// Throws error
final expression = "8(3+1)"; // A
final expression = "8(3+1"; // B
// Executes correctly
final expression = "8*(3+1)";
final Parser parser = Parser();
Expression exp = parser.parse(expression);
ContextModel cm = ContextModel();
final double result = exp.evaluate(EvaluationType.REAL, cm);
I'm aware of the syntactic requirement of the package so I'd like to properly format the expression before passing it to the parser since I cannot guarantee user input will comply to the requirement mentioned before.
What I've got so far
A. Missing an asterisk before a parenthesis:
I read about the replaceAllMapped method but I don't really know how to start from here in order to add the missing asterisks when needed.
B. Missing parenthesis within the expression. (solved)
Hypothesis
A. Missing an asterisk before a parenthesis:
I think the way is to create an array of digits, search for coincidences of a digit + parenthesis and then replace it with the addition of an asterisk like this: digit + "*" + parenthesis
Any ideas on how to solve this appropriately?

Related

PetitParser and Parentheses

Sorry, I ran into another question about using PetitParser. I've figured out my recursive issues, but now I have a problem with parentheses. If I need to be able to parse the following two expressions:
'(use = "official").empty()'
'(( 5 + 5 ) * 5) + 5'
I've tried doing something like the following:
final expression = (char('(') & any().starGreedy(char(')')).flatten() & char(')')).map((value) => ParenthesesParser(value));
But that doesnt' work on the first expression.
If I try this:
final expression = (char('(') & any().starLazy(char(')')).flatten() & char(')')).map((value) => ParenthesesParser(value));
It doesn't work on the second expression. Any suggestions on how to parse both?
I think neither of the parsers does what you want: The first parser, the greedy one with starGreedy, will consume up to the last closing parenthesis. The second parser, the lazy one with starLazy, will consume up to the first closing parenthesis.
To parse a balanced parenthesis you need recursion, so that each opening parenthesis is followed by a matching closing one:
final inner = undefined();
final parser = char('(') & inner.star().flatten() & char(')');
inner.set(parser | pattern('^)'));
In the snippet above, the inner parser is recursively trying to either parse another parenthesis pair, or otherwise it simply consumes any character that is not a closing parenthesis.

How do I parse out a number from this returned XML string in python?

I have the following string:
{\"Id\":\"135\",\"Type\":0}
The number in the Id field will vary, but will always be an integer with no comma separator. I'm not sure how to get just that value from that string given that it's string data type and not real "XML". I was toying with the replace() function, but the special characters are making it more complex than it seems it needs to be.
is there a way to convert that to XML or something that I can reference the Id value directly?
Maybe use a regular expression, e.g.
import re
txt = "{\"Id\":\"135\",\"Type\":0}"
x = re.search('"Id":"([0-9]+)"', txt)
if x:
print(x.group(1))
gives
135
It is assumed here that the ids are numeric and consist of at least one digit.
Non-regex answer as you asked
\" is an escape sequence in python.
So if {\"Id\":\"135\",\"Type\":0} is a raw string and if you put it into a python variable like
a = '{\"Id\":\"135\",\"Type\":0}'
gives
>>> a
'{"Id":"135","Type":0}'
OR
If the above string is python string which has \" which is already escaped, then do a.replace("\\","") which will give you the string without \.
Now just load this string into a dict and access element Id like below.
import json
d = json.loads(a)
d['Id']
Output :
135

Strip margin of indented triple-quote string in Purescript?

When using triple quotes in an indented position I for sure get indentation in the output js string too:
Comparing these two in a nested let
let input1 = "T1\nX55.555Y-44.444\nX52.324Y-40.386"
let input2 = """T1
X66.324Y-40.386
X52.324Y-40.386"""
giving
// single quotes with \n
"T1\x0aX55.555Y-44.444\x0aX52.324Y-40.386"
// triple quoted
"T1\x0a X66.324Y-40.386\x0a X52.324Y-40.386"
Is there any agreed upon thing like stripMargin in Scala so I can use those without having to unindent to top level?
Update, just to clarify what I mean, I'm currently doing:
describe "header" do
it "should parse example header" do
let input = """M48
;DRILL file {KiCad 4.0.7} date Wednesday, 31 January 2018 'AMt' 11:08:53
;FORMAT={-:-/ absolute / metric / decimal}
FMAT,2
METRIC,TZ
T1C0.300
T2C0.400
T3C0.600
T4C0.800
T5C1.000
T6C1.016
T7C3.400
%
"""
doesParse input header
describe "hole" do
it "should parse a simple hole" do
doesParse "X52.324Y-40.386" hole
Update:
I was asked to clarify stripMargin from Scala. It's used like so:
val speech = """T1
|X66.324Y-40.386
|X52.324Y-40.386""".stripMargin
which then removes the leading whitespace. stripMargin can take any separator, but defaults to |.
More examples:
Rust has https://docs.rs/trim-margin/0.1.0/trim_margin/
Kotlin has in stdlib: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/trim-margin.html
I guess it might sound like asking for left-pad ( :) ) but if there's something there already I'd rather not brew it myself…
I'm sorry you didn't get a prompt response to this one, but I have implemented this function here. In case the pull request isn't merged, here's an implementation that just depends on purescript-strings:
import Data.String (joinWith, split) as String
import Data.String.CodeUnits (drop, dropWhile) as String
import Data.String.Pattern (Pattern(..))
stripMargin :: String -> String
stripMargin =
let
lines = String.split (Pattern "\n")
unlines = String.joinWith "\n"
mapLines f = unlines <<< map f <<< lines
in
mapLines (String.drop 1 <<< String.dropWhile (_ /= '|'))

Why is there space at end of method names ending with an operator?

I've been learning Scala recently, and learned that for method names, if the method name ends in an operator symbol (such as defining unary_- for a class), and we specify the return type, we need a space between the final character of the method and the : which let's us specify the return type.
def unary_-: Rational = new Rational(-numer, denom)
The reasoning I have heard for this is that : is also a legal part of an identifier, so we need a way of separating the identifier and the end of the method name. But letters are legal parts of identifiers too, so why don't we need a space if we just have a method name that is all letters?
To quote the language spec (p. 12) or html:
First, an identifier can start with a letter
which can be followed by an arbitrary sequence of letters and digits. This may be
followed by underscore ‘_’ characters and another string composed of either letters
and digits or of operator characters
That is, to include operator characters into identifiers, they must be joined with an underscore.
Looking at def unary_-: Rational = new Rational(-numer, denom), with the underscore joining unary with -:, the colon is interpreted as part of the method name if there is no space. Therefore, with the colon being part of the method name, it can't find the colon precedes the return type.
scala> def test_-: Int = 1 // the method name is `test_-:`
<console>:1: error: '=' expected but identifier found.
scala> def test_- : Int = 1 // now the method name is `test_-`, and this is okay.
test_$minus: Int
If you want the colon to be part of the method name, it would have to look like this:
scala> def test_-: : Int = 1
test_$minus$colon: Int
Method names with just letters will not have this problem, because the colon isn't absorbed into the name following an underscore.

no dot between functions in map

I have the following code:
object testLines extends App {
val items = Array("""a-b-c d-e-f""","""a-b-c th-i-t""")
val lines = items.map(_.replaceAll("-", "")split("\t"))
print(lines.map(_.mkString(",")).mkString("\n"))
}
By mistake i did not put a dot between replaceAll and split but it worked.
By contrary when putting a dot between replaceAll and split i got an error
identifier expected but ';' found.
Implicit conversions found: items =>
What is going on?
Why does it work without a dot but is not working with a dot.
Update:
It works also with dot. The error message is a bug in the scala ide. The first part of the question is still valid
Thanks,
David
You have just discovered that Operators are methods. x.split(y) can also be written x split y in cases where the method is operator-like and it looks nicer. However there is nothing stopping you putting either side in parentheses like x split (y), (x) split y, or even (x) split (y) which may be necessary (and is a good idea for readability even if not strictly necessary) if you are passing in a more complex expression than a simple variable or constant and need parentheses to override the precedence.
With the example code you've written, it's not a bad idea to do the whole thing in operator style for clarity, using parentheses only where the syntax requires and/or they make groupings more obvious. I'd probably have written it more like this:
object testLines extends App {
val items = Array("a-b-c d-e-f", "a-b-c th-i-t")
val lines = items map (_ replaceAll ("-", "") split "\t")
print(lines map (_ mkString ",") mkString "\n")
}