/**
* This program demonstrates
*
* @author Alita Alice
* @version 1.0
* @Date: Created in 21:07 2020/4/18
*/
import java.util.*;
/**
* notes: 终结符,通俗的说就是不能单独出现在推导式左边的符号,也就是说终结符不能再进行
* 推导。不是终结符的都是非终结符。非终结符可理解为一个可拆分元素,而终结符是不可拆
* 分的最小元素。如:有α → β ,则α 必然是个非终结符。一般书上把非终结符用大写字母
* 表示,而终结符用小写字母表示。识别符号就是开始符。由文法产生语言句子的基本思想是:
* 从识别符号开始,把当前产生的符号串中的非终结符号替换为相应规则右部的符号串,直到
* 最终全由终结符号组成。这种替换过程称为推导或产生句子的过程,每一步成为直接推导或
* 直接产生。
*/
public class Chomsky {
private List<Producer> producers = new ArrayList<>(); //产生式集合producers
private Set<Character> vn=new HashSet<>();
private Set<Character> vt=new HashSet<>();
private Set<Character> s=new HashSet<>();
public void add(Producer producer) {
producers.add(producer);
}
public void PrintGrammar() //输出文法
{
System.out.println("产生式P为");
for (Producer producer:producers)
{
String s=producer.left+producer.right;
for(int i=0;i<s.length();i++) {
if (s.charAt(i) < 91 && s.charAt(i)>64) {
vn.add(s.charAt(i));
}
else
{
vt.add(s.charAt(i));
// vs.add(s.charAt(0));
}
}
System.out.println(producer.toString());
}
Producer p=new Producer();
p=producers.get(0);
System.out.println("开始符号S为:");
System.out.println(p.toString2());
System.out.println("非终结符VN为:");
for(char c:vn)
{
System.out.println(c+"");
}
System.out.println("终结符VT为:");
for(char c:vt)
{
System.out.println(c+"");
}
}
public boolean isZero() {
for (Producer producer : producers) {
if (producer.left.length() == 0 || producer.left.equals(producer.left.toLowerCase())) {
// 判断产生式的左部是否为空或者全部是小写,如果是则不是 0 型文法
return false;
}
}
return true;
}
public boolean isFirst() {
if (isZero()) {
for (Producer producer : producers) {
if (producer.right.length() != 0 && producer.right.length() < producer.left.length()) {
// 1 型文法必须右部长度大于左部,除了右部为ε的情况
return false;
}
}
return true;
} else {
return false;
}
}
public boolean isSecond() {
if (isFirst()) {
for (Producer producer : producers) {
if (producer.left.length() != 1 || producer.left.matches("[a-z]")) {
// 2 型文法左部必须为 1,且左部为 1 时不能为非终结符
return false;
}
}
return true;
} else {
return false;
}
}
public boolean isThird() {
if (isSecond()) {
int countLeft = 0, countRight = 0;
for (Producer producer : producers) {
if (producer.right.matches("[A-Z]?[a-z]")) {
countLeft++;
}
if (producer.right.matches("[a-z][A-Z]?")) {
countRight++;
}
}
if (countLeft == producers.size()) {
System.out.println("此文法是 3 型文法(3型文法一定是2型文法),并且是左线性文法!");
return true;
}
if (countRight == producers.size()) {
System.out.println("此文法是 3 型文法(3型文法一定是2型文法),并且是右线性文法!");
return true;
}
}
return false;
}
/**
* 判断文法的具体类型,从 3 到 0 逐步判断
*/
public void test() {
if (!isThird()) {
if (isSecond()) {
System.out.println("此文法是 2 型文法(2型文法一定是1型文法)");
} else if (isFirst()) {
System.out.println("此文法是 1 型文法(1型文法一定是0型文法)");
} else if (isZero()) {
System.out.println("此文法是 0 型文法");
} else {
System.out.println("此文法不是 0 型文法!");
}
}
}
private static final class Producer {
String left;
String right;
public Producer() {
}
public Producer(String left, String right) {
this.left = left;
this.right = right;
}
@Override
public String toString() {
return left + "->"+ right ;
}
public String toString2()
{
return left;
}
}
public static void main(String[] args) {
int count;
String[] input;
Scanner scanner = new Scanner(System.in);
Chomsky chomsky = new Chomsky();
System.out.println("请输入产生式的个数:");
count = scanner.nextInt();
System.out.println("请依次输入产生式(示例:A->ab,一行一个):");
for (int i = 0; i < count; i++) {
input = scanner.next().split("->");
try {
chomsky.add(new Producer(input[0], input[1]));
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("输入非法,请重新运行程序!!!");
System.exit(1);
}
}
chomsky.PrintGrammar();
chomsky.test();
scanner.close();
}
}```
JAVA
最新推荐文章于 2024-04-01 11:05:54 发布