Using the following grammar:
<S> -> <A> a <B> b
<A> -> <A> b | b
<B> -> a <B> | a
I am trying to get the correct output in java. I have some code
pre-written.. How can I change my code to get the correct result?
Need a new method for the grammar, ignore the other methods.
public class CFGDemo11 {
public static boolean isS(String s) {
for(int i = 0; i < s.length() -
1; i++) {
for(int j = i +
1; j <= s.length() - 1; j++) {
if(isA(s, 0, i) && isB(s, i + 1, j))
{
return true;
}
}
}
return false;
}
public static boolean isA(String s, int start, int
end) {
if(end - start + 1 < 1) {
return
false;
}
/*
if(getA(s, start, end)) {
return
true;
}
*/
return (start == end &&
s.charAt(start) == 'b') ||
(s.charAt(start) == 'b' && isA(s, start
+ 1, end))
&& s.charAt(end) == 'a';
}
public static boolean isB(String s, int start, int
end) {
if(end - start + 1 < 1) {
return
false;
}
/*
if(getB(s, start, end)) {
return
true;
}
*/
return (start == end &&
s.charAt(start) == 'a') ||
(s.charAt(start) == 'a' && isB(s, start
+ 1, end))
&& s.charAt(end) == 'b';
}
/*
public static boolean getA(String s, int start, int
end) {
return start == end &&
s.charAt(start) == 'a';
}
public static boolean getB(String s, int start, int
end) {
return start == end &&
s.charAt(start) == 'b';
}*/
public static void main(String args[]) {
System.out.println(isS("baab"));//true
System.out.println(isS("bbbab"));//false
System.out.println(isS("bbaaaaaS"));//false
System.out.println(isS("bbaab"));//true
}
}
In this grammar,
S -> AaBb
A -> Ab | b
B -> aB | a
Basically, A derives strings like b, bb, bbb, bbbb, ... bn .
And B derives strings like a, aa, aaa, aaaa, ... an .
One difference in the derivation method of A and B is that A is left recursive and B is right recursive.
Left recursion means that larger strings are generated by adding characters to the left of some other string and in right recursion, the non terminal generating the further characters are to the right of some other string.
The right side of the production A -> Ab has the non terminal A to the left of the string 'b'. Hence A is left recursive in this production. Similarly B is right recursive.
Hence S derives strings of the form AaBb which means strings of the form bnaanb.
The basic string is baab which is of length 4. (As A derives at least one 'b' and B derives at least one 'a')
Following are the logical errors I found in your code:
1. Your isS() simply takes in a string and finds a point i and a point j such that the substring from start to i is the a string generated by non terminal A and from i+1 to j is generated by B.
This however does not make sense. The correct approach instead is to write isS() such that
2. Your isB() takes a string s, a start index and end index and returns true in two cases:
Your logic here is correct except for one thing: You must not check whether the character at the end is 'b'. This is because (B derives aB or a) and not (B derives aBb or a).
3. Your isA() has the same error as isB() (A->Ab | b and not A->Aba | b). There is one additional error though: according to your code you've thought of A as right recursive like B (A->bA | b). This should corrected by checking the following for isA() to return true:
The corrected working code is as follows:
public class CFGDemo11 {
public static boolean isS(String s) {
if(s.length() < 4)
return
false;
for(int i = 0; i <
s.length() - 1; i++) {
if(isA(s, 0, i) && s.charAt(i+1) == 'a' && isB(s, i
+ 2, s.length()-2) && s.charAt(s.length()-1) == 'b')
{
return true;
}
}
return false;
}
public static boolean isA(String s, int start, int
end) {
if(end - start + 1 < 1)
{
return
false;
}
return (start == end
&& s.charAt(start) == 'b') ||
(s.charAt(end) == 'b' && isA(s, start, end-1));
}
public static boolean isB(String s, int start, int
end) {
if(end - start + 1 < 1)
{
return
false;
}
return (start == end
&& s.charAt(start) == 'a') ||
(s.charAt(start) == 'a' && isB(s, start + 1, end));
}
public static void main(String args[]) {
System.out.println(isS("baab"));//true
System.out.println(isS("bbbab"));//false
System.out.println(isS("bbaaaaaS"));//false
System.out.println(isS("bbaab"));//true
}
}
Output:
true
false
false
true
Thank you.