Mu
so small — only one operator and numbers — you can simply iterate through the input and check each character. enum Token { case parensOpen case op(String) case number(Int) case parensClose } struct Lexer { static func tokenize(_ input: String) -> [Token] { return input.characters.flatMap { switch $0 { case "(": return Token.parensOpen case ")": return Token.parensClose case "s": return Token.op($0.description) default: if "0"..."9" ~= $0 { return Token.number(Int($0.description)!) } } return nil } } } let input = "(s (s 4 5) 4)" let tokens = Lexer.tokenize(input)
expression: parensOpen operator primaryExpression primaryExpression parensClose primaryExpression: expression | number parensOpen: "(" parensClose: ")" operator: "s" number: [0-9]
Mu
grammar is a contextless grammar, which means that it describes all possible variations of strings in a language. The parser starts from the top (root of the generated tree) and moves to the lowest node. func parseExpression() -> ExpressionNode { ... firstPrimaryExpression = parsePrimaryExpression() secondPrimaryExpression = parsePrimaryExpression() ... } func parseExpression() -> PrimaryExpressionNode { return parseExpression() || parseNumber() }
indirect enum PrimaryExpressionNode { case number(Int) case expression(ExpressionNode) } struct ExpressionNode { var op: String var firstExpression: PrimaryExpressionNode var secondExpression: PrimaryExpressionNode } struct Parser { var index = 0 let tokens: [Token] init(tokens: [Token]) { self.tokens = tokens } mutating func popToken() -> Token { let token = tokens[index] index += 1 return token } mutating func peekToken() -> Token { return tokens[index] } mutating func parse() throws -> ExpressionNode { return try parseExpression() } mutating func parseExpression() throws -> ExpressionNode { guard case .parensOpen = popToken() else { throw ParsingError.unexpectedToken } guard case let Token.op(_operator) = popToken() else { throw ParsingError.unexpectedToken } let firstExpression = try parsePrimaryExpression() let secondExpression = try parsePrimaryExpression() guard case .parensClose = popToken() else { throw ParsingError.unexpectedToken } return ExpressionNode(op: _operator, firstExpression: firstExpression, secondExpression: secondExpression) } mutating func parsePrimaryExpression() throws -> PrimaryExpressionNode { switch peekToken() { case .number: return try parseNumber() case .parensOpen: let expressionNode = try parseExpression() return PrimaryExpressionNode.expression(expressionNode) default: throw ParsingError.unexpectedToken } } mutating func parseNumber() throws -> PrimaryExpressionNode { guard case let Token.number(n) = popToken() else { throw ParsingError.unexpectedToken } return PrimaryExpressionNode.number(n) } } //MARK: Utils extension ExpressionNode: CustomStringConvertible { public var description: String { return "\(op) -> [\(firstExpression), \(secondExpression)]" } } extension PrimaryExpressionNode: CustomStringConvertible { public var description: String { switch self { case .number(let n): return n.description case .expression(let exp): return exp.description } } } let input = "(s 2 (s 3 5))" let tokens = Lexer.tokenize(input) var parser = Parser(tokens: tokens) var ast = try! parser.parse()
enum InterpreterError: Error { case unknownOperator } struct Interpreter { static func eval(_ expression: ExpressionNode) throws -> Int { let firstEval = try eval(expression.first) let secEval = try eval(expression.second) if expression.op == "s" { return firstEval + secEval } throw InterpreterError.unknownOperator } static func eval(_ prim: PrimaryExpressionNode) throws -> Int { switch prim { case .expression(let exp): return try eval(exp) case .number(let n): return Int(n) } } } let input = "(s (s 5 2) 4)" let tokens = Lexer.tokenize(input) var parser = Parser(tokens: tokens) let ast = try! parser.parse() try! Interpreter.eval(ast)
let input = "(s (s 4 5) 4)
let tokens = Lexer.tokenize(input)
var parser = Parser(tokens: tokens) let ast = try! parser.parse()
let result = try! Interpreter.eval(ast)
Source: https://habr.com/ru/post/315068/
All Articles