How to parse certain tokens out of a String? - java

Could someone please help me parse integer values and arithematic operators from a java string.
For ex:
String rule = "itemCount < 10 and itemCount >= 20";
From the rule String I need to retrieve, <, 10, >= and 20 which will then be displayed in the jsp.

for (int i =0; i < rule.length; ++i) {
if (rule[i] == "<") {
// Code for retrieving <
} else if (rule[i] == ">=")
// Code for retrieving >=
} else {
tryParse(rule, i);
}
}
tryParse is the function that will recursively try to parse integers until the biggest sequence of consecutive digits found and updates the value of i

Does a regular expression help you?
Maybe something like:
(\w+) (<|<=|==|>|>=) (\w+) (\w+) (\w+) (<|<=|==|>|>=) (\w+)
(can be optimized for sure)
When matching this expression against your string you should get 7 groups with following contents:
1: itemCount
2: <
3: 10
4: and
5: itemCount
6: >=
7: 20
See the Pattern Class documentation for more details.
But in general I am not sure if this is what you want to do.
Maybe its better to switch to a more abstract way to define your expression instead of writing it into a string.
What about something like this:
Rule rule = Rule.AND(
Rule.SMALLER(itemCount, 10),
Rule.GREATER_OR_EQUAL(itemCount, 20)
);
boolean result = rule.getResult();

Related

Java Regex to Match a Number Within a Range

I'm trying to craft a Java regular expression to identify if a number (which I don't know until execution time) is within a range (and that range I also don't know until execution time).
Specifically, I'm trying to use Cisco's PRIME compliance module to validate my switch has no inactive VLANs (for this question, a VLAN is just a number), but PRIME uses Java regular expression syntax.
I know that the specific switch command I'm evaluating uses a syntax like:
switchport trunk allowed vlan 1,20,37,45,90-101,300-502,904-2044
How, then, can I tell if VLAN "x" is in any of those ranges?
If x = 20, it should match.
If x = 90, it should match.
If x = 900, it should fail.
If x = 1043, it should match.
Any ideas?
Edit: Unfortunately, the RegEx listed here is for ranges that are known; the examples are all hard-coded ranges. I need something that takes an unknown x, y, and z, where all x, y, and z might possibly be 1, 2, 3, or 4 digits, and matches if z is between x and y when written as "x-y".
Is there a way to take the string "x-y", parse it into \1 and \2 that are understood to be numbers, and match if (z >= \1 && z <= \2)?
I've tried looking at things like lookahead and lookbehind and crazy/obscure Java-compatible regex structures, but my head quickly got spun into the 4th dimension.
I don't think this should be done with a regular expression. Personally I'd use a regex to check if it's the right format, i.e. check if the string matches "VLAN ([0-9]+(-[0-9]+)?)(,([0-9]+(-[0-9]+)?))*", then split the latter part on the commas and use integer parsing from there, depending on if there is a '-' in there or not you can check the ranges.
For instance like this: https://jsfiddle.net/gcb9pm7f/15/
function testRanges()
{
var str = document.getElementById("textField").value;
var test = parseInt(document.getElementById("numberField").value);
str = str.toUpperCase(); // VLAN big
var regex = /^VLAN ([0-9]+(-[0-9]+)?)(,([0-9]+(-[0-9]+)?))*$/g;
if (regex.test(str))
{
str = str.substring(5, str.length); // remove 'VLAN'
var splitArray = str.split(',');
for (var idx = 0; idx < splitArray.length; idx++)
{
var rangeStr = splitArray[idx];
if (rangeStr.includes('-'))
{
// range, check both values.
var a = parseInt(rangeStr.split('-')[0]);
var b = parseInt(rangeStr.split('-')[1]);
if (a > b)
{
if (test >= b && test <= a) return true; // range is inclusive
}
else // a <= b
{
if (test <= b && test >= a) return true; // range is inclusive
}
}
else // not a range, single value
{
if (parseInt(rangeStr) === test) return true;
}
}
}
return false; // no match or regex not matching.
}
Adjust to your programming language as needed. Should be fairly straight forward.

parser with integer literals

I am looking for an easy and efficient way to implement a set of numbers in a lexical parser in java. For example my input code is as follows :
"6+9" ,
the output would have to be a little like this :
Number : 6
Sign : +
Number: 9
The issue I have is i have no way to recognize the number other than to implement it as follows :
static char INTVALUE = ('0') ;
which means I would have to manually enter each number from 0 to 9 and I don't know If such a method would even allows to have a number such as 85 in my input .
This is for a homework assignment by the way
Thanks .
For the simplest grammars you can indeed use regular expressions:
import java.util.regex.*;
// ...
String expression = "(10+9)*2";
Pattern pattern = Pattern.compile("\\s*(\\d+|\\D)\\s*");
Matcher matcher = pattern.matcher(expression);
while (matcher.find()) {
String token = matcher.group(1);
System.out.printf("%s: '%s'%n",
token.matches("\\d+") ? "Number" : "Symbol",
token);
}
In a compiler construction course you will probably be expected to construct an NFA and then transform that into a minimal DFA by implementing an algorithm like this one. In real life you would normally use a tool like ANTLR or JLex.
Why dont use regular expressions for this. It sounds a best fit for what you are attempting to do.
Its fairly simple to learn. Look at Character classes (\d) and Quatifiers(+ ?) in this cheatsheet
To check for integers and doubles us the following.
aStr.matches("-?\\d+(\\.\\d+)?");
For just integers:
aStr.matches("-?\\d+");
You can also do something simple like this:
public List<Token> lex(String s) {
List<Token> result = new ArrayList<Token>();
int pos = 0;
int len = s.length();
while (pos < len) {
switch (s.charAt(pos)) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
int end = pos;
do {
++end;
} while (end < len && s.charAt(end) >= '0' && s.charAt(end) <= '9');
result.add(new Number(s.substring(pos, end)));
pos = end;
break;
}
case '+':
{
result.add(new Operator("+"));
++pos;
break;
}
// ...
}
}
return result;
}

Java regex: How to replace all character inside a bracket?

How do I able to replace:
((90+1)%(100-4)) + ((90+1)%(100-4/(6-4))) - (var1%(var2%var3(var4-var5)))
with
XYZ((90+1),(100-4)) + XYZ((90+1),100-4/(6-4)) - XYZ(var1,XYZ(var2,var3(var4-var5)))
with regex?
Thanks,
J
this doesn't really look like a very good job for a regex. It looks like you might want to write a quick recursive descent parser instead. If I understand you correctly, you want to replace the infix operator % with a function name XYZ?
So (expression % expression) becomes XYZ(expression, expression)
This looks like a good resource to study: http://www.cs.uky.edu/~lewis/essays/compilers/rec-des.html
I don't know much about regex, but try looking at this, especially 9 and 10:
http://www.mkyong.com/regular-expressions/10-java-regular-expression-examples-you-should-know/
And of course:
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html
You could at least check them out until an in depth answer comes along.
See this code:
String input = "((90+1)%(100-4)) + ((90+1)%(100-4/(6-4))) - (var1%(var2%var3(var4-var5)))";
input = input.replaceAll("%", ",");
int level = 0;
List<Integer> targetStack = new ArrayList<Integer>();
List<Integer> splitIndices = new ArrayList<Integer>();
// add the index of last character as default checkpoint
splitIndices.add(input.length());
for (int i = input.length() - 1; i >= 0; i--) {
if (input.charAt(i) == ',') {
targetStack.add(level - 1);
} else if (input.charAt(i) == ')') {
level++;
}
else if (input.charAt(i) == '(') {
level--;
if (!targetStack.isEmpty() && level == targetStack.get(targetStack.size() - 1)) {
splitIndices.add(i);
}
}
}
Collections.reverse(splitIndices); // reversing the indices so that they are in increasing order
StringBuilder result = new StringBuilder();
for (int i = 1; i < splitIndices.size(); i++) {
result.append("XYZ");
result.append(input.substring(splitIndices.get(i - 1), splitIndices.get(i)));
}
System.out.println(result);
The output is as you expect it:
XYZ((90+1),(100-4)) + XYZ((90+1),(100-4/(6-4))) - XYZ(var1,XYZ(var2,var3(var4-var5)))
However keep in mind that it is a bit hacky and it might not work exactly as you expect it. Btw, I had to change a bit the output I added couple of brackets: XYZ((90+1), ( 100-4/(6-4 ) )) because otherwise you were not following your own conventions. Hopefully this code helps you. For me it was a good exercise at least.
Would it satisfy your requirements to do the following:
Find ( at first position or preceded by space and replace it with XYZ(
Find % and replace it with ,
If those two instructions are sufficient and satisfactory, then you could transform the original string in three "moves":
Replace ^\( with XYZ(
Replace \( with XYZ(
Replace % with ,

Java String Manipulation: extracting integer and float from string based on pattern

I have the following two possible contents of a String.
Obviously the amounts always vary and I would like to extract the key information and
Case 0: pricesString = ""
Case 1: pricesString = "$0.023"
Case 2: pricesString = "10+: $1.46 100+: $0.16 500+: $0.04"
In Case 0 I would like to do nothing.
In Case 1 I would like to perform:
article.addPrice(1, 0.023);
In Case 2 I would like to perform:
article.addPrice(10, 1.46);
article.addPrice(100, 0.16);
article.addPrice(500, 0.04);
How can I extract this information so I can can call article.addPrice with the float and integer values contained?
That looks like a job for regex:
String pricesString = "10+: $1.46 100+: $0.16 500+: $0.04";
Pattern p = Pattern.compile("(\\d+)\\+: \\$(\\d\\.\\d\\d)");
Matcher m = p.matcher(pricesString);
while (m.find()) {
Intger.parseInt(m.group(1));
Double.parseDouble(m.group(2));
}
You can choose between the 3 cases by a simple .length() check. The code above is for the last case. The rest is eaiser
Apply the regex \d+\.?\d* as often as you can. The array of the results can be checked whether it contains 0, 1 or more values.
If there are 0, it is Case 0.
If there is one, it is Case 1. You can edd it with qunantity 1 to the articles.
If there are more, you can loop with something like
for(int i = 0; i < result.length / 2; i++) {
articles.addArticle(Integer.parseInt(result[i]), Double.parseDouble(result[i+1]));
}

Regexp to check if parentheses are balanced [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Can regular expressions be used to match nested patterns?
I am writing a regexp to check if the input string is a correct arithmetic expression. The problem is checking if there are enough opening and closing parentheses.
Expressions:
(1)
(((1)
((1))))
I think lookahead and lookbehind are useful here but for now I could check only one kind. I'm using Java, if it matters.
You shouldn't use regular expression to do this. Instead you can iterate over the string character by character and keep track of the nesting level.
Initially the nesting is 0. When you see a ( increase the nesting by 1, and when you see ) decrease the nesting. The expression is correctly balanced if the final nesting is 0 and the nesting never goes below 0.
public static boolean checkParentheses(String s) {
int nesting = 0;
for (int i = 0; i < s.length(); ++i)
{
char c = s.charAt(i);
switch (c) {
case '(':
nesting++;
break;
case ')':
nesting--;
if (nesting < 0) {
return false;
}
break;
}
}
return nesting == 0;
}
You need to be using a parser to do this, not a regex. See this question.
Why not just count the opening and closing parens like so?
String expression = "((1+x) - 3 * 4(6*9(12+1)(4+(2*3+(4-4)))))";
int open = 0;
for(int x = 0; x < open; x++){
if(expression[x] == '(')
open++;
else if(expression[x] == ')')
open--;
}
if (open != 0)
// Not a valid expression
Of course this only checks that you have the right amount - someone could write '))3*4((' and it would be validated using this method.

Categories