祖母に自分のプログラミング言語の書き方を説明します

これは、小さなプログラミング言語(Mu)の作成方法を説明しようとする遊び場です。 こちらからオープンソースライブを見るか、 こちらからダウンロードできます 。 今すぐチュートリアルを読むことができます。



画像



プログラミング言語の作成(Swiftで)



独自のプログラミング言語を作成するには、コンピューターサイエンスの学位を取得する必要はありません。3つの基本的な手順を理解すれば十分です。



言語:ムー(μ)



Muは、後置演算子、二項演算、および「1桁」の数字を含む最小限の言語です。



例: (s 2 4)または(s(s 4 5)4)または(s(s 4 5)(s 3 2))...



手順:





レクサー



コンピューターサイエンスでは、字句解析は、「トークン」と呼ばれる文字のシーケンス(単語の文字のグループなど)を取得するために、文字の入力シーケンス(たとえば、プログラミング言語のソースコードなど)を解析的に解析するプロセスです。



プロセスの出力でトークンとして識別される入力シーケンスの文字のグループは、トークンと呼ばれます。 字句解析のプロセスでは、文字の入力シーケンスからのトークンの認識と選択が実行されます。

-ウィキペディア



例:



画像



Mu



非常に小さいため(演算子と数字は1つだけです)、入力を反復処理して各文字をチェックできます。



 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



は、文脈に依存しない文法です。つまり、言語の文字列のすべての可能なバリエーションを記述します。 パーサーは最上部(生成されたツリーのルート)から開始し、最下部のノードに移動します。



ヒント:コードは、文法を直接表現するものでなければなりません。



 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()
      
      





通訳



コンピューターサイエンスでは、インタープリターは、プログラミング言語またはスクリプト言語で記述された命令を、最初にマシンコードにコンパイルすることなく順次実行するプログラムです。 (ウィキペディア)



例:



Muインタープリターは、ASTを通過して値を計算し、子ノードに演算子を適用します。



画像



 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)
      
      





おわりに



画像






 var parser = Parser(tokens: tokens) let ast = try! parser.parse()
      
      







資源








出版物サポート-Edisonアスファルトプラントの自動化 と支払いシステムと端末の開発を専門とする会社。



All Articles