实现一个简单语言(一)

没有赋值的变量可以直接使用,缺点:变量名错误不易发现

前面实现了简单的计算器,在动作中直接计算

下面一步一步实现一个语言

1.变量  (只能由英文构成)

2.数字 (int)

2.赋值表达式

3.加法表达式

4.语句

语法定义

S' -> S
S -> L//语句集合
L -> L T// 语句集合 语句
L -> T// 语句
T -> E ;// 表达式 冒号
E -> identifier = A// 赋值表达式
A -> A + U// 加法表达式
A -> A - U// 减法表达式
A -> U// 一元表达式
U -> P //基本表达式
P -> identifier// 变量
P -> digit/ 数字

语句:
a = 3;
b = 4;
a = a + b;
b = a - 1;
结果
a = 7
b = 6;

前面没有实现词法分析器,简单用空格分隔,现在实现一个简单的词法分析器
需要能够接受下面的语句
a = 5 ; b = a + 3;b = b + a;
解析为词法符号串
public class Lexical {

    // 输入
    private String input;
    private Set<String> terminals;// 保留字,终结符号

    // 计算用
    private char[] arr;
    private int idx;
    private List<Character> tmp;

    // 结果
    private List<Symbol> result;

    public Lexical(Collection<String> terminals, String input) {
        this.terminals = terminals.stream().collect(Collectors.toSet());
        this.input = input;
        this.result = new ArrayList<>();
    }

    public List<Symbol> parse() {
        arr = input.toCharArray();
        char c;
        while (idx < arr.length) {
            c = currCh();
            if (Character.isDigit(c)) {
                parseDigit();
            } else if (Character.isLetter(c)) {
                parseIdentifier();
            } else if (Character.isSpaceChar(c)) {
                nextCh();
            } else {
                StringBuilder sb = new StringBuilder();
                sb.append(c);
                String str = sb.toString();
                if (terminals.contains(str)) {
                    result.add(Terminal.of(str));
                    nextCh();
                } else {
                    throw new RuntimeException("非法字符串");
                }
            }
        }
        return this.result;
    }

    private void nextCh() {
        idx++;
    }

    private char currCh() {
        return arr[idx];
    }

    public void parseIdentifier() {
        tmp = new ArrayList<>();
        char c;
        while (idx < arr.length) {
            c = currCh();
            if (Character.isLetter(c)) {
                tmp.add(c);
                nextCh();
            } else {
                break;
            }
        }
        String str = tmp.stream().map(String::valueOf).collect(Collectors.joining(""));
        result.add(Terminal.of("identifier", str));
    }

    public void parseDigit() {
        tmp = new ArrayList<>();
        char c;
        while (idx < arr.length) {
            c = currCh();
            if (Character.isDigit(c)) {
                tmp.add(c);
                nextCh();
            } else {
                break;
            }
        }
        String str = tmp.stream().map(String::valueOf).collect(Collectors.joining(""));
        result.add(Terminal.of("digit", IntExpression.of(Integer.parseInt(str))));
    }
}

 

posted @ 2024-01-27 00:08  kashin05  阅读(32)  评论(0)    收藏  举报