JAVA

/**
 * 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();
    }
}```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值