9b4aa785创建于 1月20日历史提交
package egg

import std.convert.*
import std.regex.*
import std.collection.*

// 定义特殊字符枚举
enum SpecialChar {
    | Quote           // "
    | Hash            // #
    | LeftParen       // (
    | RightParen      // )
    | Minus           // -
    | Newline         // \n
    | Space           // 空格
    | Tab             // \t
    | CarriageReturn  // \r

    // 获取字符的 UInt8 值
    public func getValue(): UInt8 {
        match (this) {
            case Quote => 34
            case Hash => 35
            case LeftParen => 40
            case RightParen => 41
            case Minus => 45
            case Newline => 10
            case Space => 32
            case Tab => 9
            case CarriageReturn => 13
        }
    }

    // 检查给定字符是否匹配这个枚举值
    public func matches(c: UInt8): Bool {
        return c == getValue()
    }

    // 检查字符是否为空白字符
    public static func isWhitespace(c: UInt8): Bool {
        return Space.matches(c) || Tab.matches(c) || Newline.matches(c) || CarriageReturn.matches(c)
    }

    // 检查字符是否为有效的单词字符
    public static func isValidWordChar(c: UInt8): Bool {
        if (c.isAsciiLetter()) {
            return true
        }
        // 检查特殊字符
        let specialChars = "+-*/=<>!?"
        for (ch in specialChars) {
            if (c == UInt8(ch)) {
                return true
            }
        }
        return false
    }
}

class Parser {
    var input: String
    var pos: Int64

    public init(input: String) {
        this.input = input
        this.pos = 0
    }

    // 辅助函数跳过空格和注释
    func skipSpace(): Unit {
        while (pos < input.size) {
            let c: UInt8 = input[pos]
            // 跳过注释(以 # 开始)
            if (Hash.matches(c)) {
                // 跳过到换行符
                while (pos < input.size && !Newline.matches(input[pos])) {
                    pos++
                }
            } else if (SpecialChar.isWhitespace(c)) {
                pos += 1
            } else {
                break
            }
        }
    }

    public func parse(program: String): Expression {
        this.input = program
        this.pos = 0
        let res = parseExpression()
        skipSpace()
        if (pos < input.size) {
            throw ParseException("程序结束后出现意外文本 " + input[pos..input.size])
        }
        return res
    }

    func parseExpression(): Expression {
        skipSpace()
        if (pos >= input.size) {
            throw ParseException("输入意外结束,需要更多内容")
        }
        let c: UInt8 = input[pos]
        
        if (Quote.matches(c)) {
            return parseStringLiteral()
        } else if (c.isAsciiNumber() || (pos + 1 < input.size && Minus.matches(input[pos]) && input[pos + 1].isAsciiNumber())) {
            return parseNumberLiteral()
        } else if (SpecialChar.isValidWordChar(c)) {
            return parseWord()
        } else if (LeftParen.matches(c)) {
            return parseApply()
        } else {
            throw ParseException("无法解析的表达式" + c.toString())
        }
    }

    func parseStringLiteral(): ValueExpression {
        pos += 1
        let start = pos
        // 查找结束引号
        while (pos < input.size && !Quote.matches(input[pos])) {
            pos += 1
        }
        if (pos >= input.size) {
            throw ParseException("字符串没有结束")
        }
        let str: String = input[start..pos]
        pos += 1
        return ValueExpression(Value<String>(str))
    }

    func parseNumberLiteral(): Expression {
        let regex = Regex("^-?\\d+(\\.\\d+)?([eE][-+]?\\d+)?")
        let matchData = regex.find(input[pos..input.size]).getOrThrow({=> ParseException("期望一个数字")})
        let str = matchData.matchString()
        pos += str.size
        let num = Float64.parse(str)
        return ValueExpression(Value<Float64>(num))
    }

    func parseWord(): Expression {
        let regex = Regex("^[\\w+*/=<>!?-]+")
        let matchData = regex.find(input[pos..input.size]).getOrThrow({=> ParseException("期望一个单词(标识符)")})
        let str = matchData.matchString()
        pos += str.size
        if (str == "true") {
            return ValueExpression(Value<Bool>(true))
        } else if (str == "false") {
            return ValueExpression(Value<Bool>(false))
        } else {
            return WordExpression(str)
        }
    }

    func parseApply(): Expression {
        pos += 1
        skipSpace()
        let op = parseExpression()
        let args = ArrayList<Expression>()
        while (true) {
            skipSpace()
            if (pos >= input.size) {
                throw ParseException("应用表达式未闭合,期望 ')'")
            }
            if (RightParen.matches(input[pos])) {
                pos += 1
                break
            }
            let arg = parseExpression()
            args.add(arg)
        }
        return ApplyExpression(op, args.toArray())
    }
}

class ParseException <: Exception {
    public init(message: String) {
        super(message)
    }
}