{
    "componentChunkName": "component---src-templates-post-js",
    "path": "/top-down-operator-precedence-zai-gui-xia-jiang-gou-wen-jie-xi-pratt-parser-niokeruexpression-shi-nojie-xi-ast-chou-xiang-gou-wen-mu-gou-zhu-chu-li-wozhui-u/",
    "result": {"data":{"ghostPost":{"id":"Ghost__Post__60fa7eeb3986b000013a3a22","title":"Top down operator precedence(再帰下降構文解析 Pratt Parser)におけるExpression(式)の解析、AST(抽象構文木)構築 処理を追う","slug":"top-down-operator-precedence-zai-gui-xia-jiang-gou-wen-jie-xi-pratt-parser-niokeruexpression-shi-nojie-xi-ast-chou-xiang-gou-wen-mu-gou-zhu-chu-li-wozhui-u","featured":false,"feature_image":"https://ghost.tech.anti-pattern.co.jp/content/images/2022/04/1_eDvHceZDIDp2m1XbK8RFJg.png","excerpt":"Top down operator precedence(再帰下降構文解析 Pratt\nParser)におけるExpression(式)の解析、AST(抽象構文木)構築 処理を追う\nGoで作る インタプリタ\nGo言語でつくるインタプリタ | Thorsten Ball, 設樂 洋爾 |本 | 通販 | AmazonAmazonでThorsten Ball, 設樂\n洋爾のGo言語でつくるインタプリタ。アマゾンならポイント還元本が多数。Thorsten Ball, 設樂\n洋爾作品ほか、お急ぎ便対象商品は当日お届けも可能。またGo言語でつくるインタプリタもアマゾン配送商品なら通常配送無料。AmazonThorsten Ball\n[https://www.amazon.co.jp/dp/4873118220/ref=cm_sw_r_tw_dp_U_x_E91IDbNW6D0K4]\n\n死ぬほどおすすめなので是非、\n\nGoの基礎とTDDの基礎、簡単なデザインパターンの理解があるとよりよい。むしろそれらを知っている人にかなりおすすめの本である。\n\nこの本に出てくる Pratt ParserによるAS","custom_excerpt":null,"visibility":"public","created_at_pretty":"23 July, 2021","published_at_pretty":"25 September, 2019","updated_at_pretty":"21 April, 2022","created_at":"2021-07-23T17:33:47.000+09:00","published_at":"2019-09-26T00:00:00.000+09:00","updated_at":"2022-04-21T17:07:34.000+09:00","meta_title":null,"meta_description":null,"og_description":null,"og_image":null,"og_title":null,"twitter_description":null,"twitter_image":null,"twitter_title":null,"authors":[{"name":"Kohei Kondo","slug":"kooooohe","bio":null,"profile_image":"https://ghost.tech.anti-pattern.co.jp/content/images/2022/04/MVIMG_20180910_102813.png","twitter":"@kooooohe_","facebook":null,"website":null}],"primary_author":{"name":"Kohei Kondo","slug":"kooooohe","bio":null,"profile_image":"https://ghost.tech.anti-pattern.co.jp/content/images/2022/04/MVIMG_20180910_102813.png","twitter":"@kooooohe_","facebook":null,"website":null},"primary_tag":{"name":"Go","slug":"go","description":null,"feature_image":null,"meta_description":null,"meta_title":null,"visibility":"public"},"tags":[{"name":"Go","slug":"go","description":null,"feature_image":null,"meta_description":null,"meta_title":null,"visibility":"public"},{"name":"golang","slug":"golang","description":null,"feature_image":null,"meta_description":null,"meta_title":null,"visibility":"public"},{"name":"interpreter","slug":"interpreter","description":null,"feature_image":null,"meta_description":null,"meta_title":null,"visibility":"public"},{"name":"TopDownOperatorPrecednce","slug":"topdownoperatorprecednce","description":null,"feature_image":null,"meta_description":null,"meta_title":null,"visibility":"public"}],"plaintext":"Top down operator precedence(再帰下降構文解析 Pratt\nParser)におけるExpression(式)の解析、AST(抽象構文木)構築 処理を追う\nGoで作る インタプリタ\nGo言語でつくるインタプリタ | Thorsten Ball, 設樂 洋爾 |本 | 通販 | AmazonAmazonでThorsten Ball, 設樂\n洋爾のGo言語でつくるインタプリタ。アマゾンならポイント還元本が多数。Thorsten Ball, 設樂\n洋爾作品ほか、お急ぎ便対象商品は当日お届けも可能。またGo言語でつくるインタプリタもアマゾン配送商品なら通常配送無料。AmazonThorsten Ball\n[https://www.amazon.co.jp/dp/4873118220/ref=cm_sw_r_tw_dp_U_x_E91IDbNW6D0K4]\n\n死ぬほどおすすめなので是非、\n\nGoの基礎とTDDの基礎、簡単なデザインパターンの理解があるとよりよい。むしろそれらを知っている人にかなりおすすめの本である。\n\nこの本に出てくる Pratt ParserによるASTの構築の理解が多少難解に感じたので、処理を図とともに追っていこうと思う。\n前提\nlexical Analyze（字句解析）は完了している。\n\n今回作っている言語には、\n\nPrefix Operator(前置演算子)とInfix Operator(中置演算子)は存在し、\n\nPostfix Operator(後置演算子）は存在しない。\n\nTop down operator precedence とは?\n>情報科学の分野において、 Prattパーサ は文法規則の代わりにトークンの意味ごとに関連付けを作るように改良された再帰下降構文解析\n[https://ja.wikipedia.org/wiki/%E5%86%8D%E5%B8%B0%E4%B8%8B%E9%99%8D%E6%A7%8B%E6%96%87%E8%A7%A3%E6%9E%90]\nのひとつ。 https://ja.wikipedia.org/wiki/Prattパーサ\n[https://ja.wikipedia.org/wiki/Pratt%E3%83%91%E3%83%BC%E3%82%B5] より\n\n簡単に説明するとTokeのタイプごとに構文解析の関数を呼び出し、Abstruct Syntax Tree(抽象構文木)(以下 AST)を形成する\n\nExpression (式)とは\n名前の通り式のことを指す。\n\n例: 3+ 2+ 1;\n\n8 単体でも式となる。\n\nちなみに、let x = 5 + 3 + 5;の場合は 式が 5 + 3 + 5;であり\n\n文が let x = 5 + 3 + 5; となる。\n\n今回のASTはこれを ((3+2)+1)と表現したいのである。\n今回見ていく例は\n\n-3 + 10 * 2 + 1;\n\nの構文解析となる。\n\n(((-3) + (10 * 2)) + 1);を表すASTを作っていく。\n\n図式すると。\n\nMain Codes\nPrecedence (優先度)\n例： +(SUM)より *(PRODUCT)のほうが数値が高いので優先度が高い。\n\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go\n- precedence.goGist262588213843476\n[https://gist.github.com/kooooohe/4a9852c5b9c7c44dde9e1a709c7ab75b]const (\n\tLOWEST iota + 1 \n\tEQUALS          // ==\n\tLESSGRETER      // > or <\n\tSUM             // +\n\tPRODUCT         // *\n\tPREFIX          // -X or !X\n\tCALL            // myFunction(X)\n)\n\n\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う] token\nprecedences[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]\ntoken precedences - tokenprecedences.goGist262588213843476\n[https://gist.github.com/kooooohe/bafc9452d3b921a586015d0ce82cb737]var precedences = map[token.TokenType]int{\n\ttoken.EQ:       EQUALS,\n\ttoken.NOT_EQ:   EQUALS,\n\ttoken.LT:       LESSGRETER,\n\ttoken.GT:       LESSGRETER,\n\ttoken.PLUS:     SUM,\n\ttoken.MINUS:    SUM,\n\ttoken.SLASH:    PRODUCT,\n\ttoken.ASTERISK: PRODUCT,\n}\n\n\n最初に呼ばれるコード\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]\nparseExpressionStatement.go\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]\nparseExpressionStatement.go - parseExpressionStatement.goGist262588213843476\n[https://gist.github.com/kooooohe/57fcf2b867adb0a940f8918dff385470][\nfunc (p *Parser) parseExpressionStatement() *ast.ExpressionStatement {\n\tstmt := &ast.ExpressionStatement{Token: p.curToken}\n\n\tstmt.Expression = p.parseExpression(LOWEST)\n\n\tif p.peekTokenIs(token.SEMICOLON) {\n\t\tp.nextToken()\n\t}\n\n\treturn stmt\n}\n\n\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]parseExpression.go\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]parseExpression.go\n- parseExpression.goGist262588213843476\n[https://gist.github.com/kooooohe/4ae9c18205aaa33128d65df9c5cf306c]func (p *Parser) parseExpression(precedence int) ast.Expression {\n\tprefix := p.prefixParseFns[p.curToken.Type]\n\tif prefix == nil {\n\t\tp.noPrefixParseFnError(p.curToken.Type)\n\t\treturn nil\n\t}\n\tleftExp := prefix()\n\n\tfor !p.peekTokenIs(token.SEMICOLON) && precedence < p.peekPrecedence() {\n\t\tinfix := p.infixParseFns[p.peekToken.Type]\n\t\tif infix == nil {\n\t\t\treturn leftExp\n\t\t}\n\n\t\tp.nextToken()\n\t\tleftExp = infix(leftExp)\n\t}\n\treturn leftExp\n}\n\n\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.goparseInfixExpression.go\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.goparseInfixExpression.go\n- parseInfixExpression.goGist262588213843476\n[https://gist.github.com/kooooohe/07c088ac44e4aaf9d6ddd184657d2cc3]func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression {\n\texpression := &ast.InfixExpression{\n\t\tToken:    p.curToken,\n\t\tOperator: p.curToken.Literal,\n\t\tLeft:     left,\n\t}\n\n\tprecedence := p.curPrecedence()\n\tp.nextToken()\n\texpression.Right = p.parseExpression(precedence)\n\n\treturn expression\n}\n\n\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go\nparsePrefixExpression.go\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go\nparsePrefixExpression.go - parsePrefixExpression.goGist262588213843476\n[https://gist.github.com/kooooohe/15318939da38846f73a562affc8a00c3]func (p *Parser) parsePrefixExpression() ast.Expression {\n\texpression := &ast.PrefixExpression{\n\t\tToken:    p.curToken,\n\t\tOperator: p.curToken.Literal,\n\t}\n\n\tp.nextToken()\n\n\texpression.Right = p.parseExpression(PREFIX)\n\n\treturn expression\n}\n\n\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go\nparseIntegerLiteral.go\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go\nparseIntegerLiteral.go - parseIntegerLiteral.goGist262588213843476\n[https://gist.github.com/kooooohe/c91d7f5f9480da4c54058846663a1962]func (p *Parser) parseIntegerLiteral() ast.Expression {\n\tlit := &ast.IntegerLiteral{Token: p.curToken}\n\n\tvalue, err := strconv.ParseInt(p.curToken.Literal, 0, 64)\n\tif err != nil {\n\t\tmsg := fmt.Sprintf(\"could not parse %q as integer\", p.curToken.Literal)\n\t\tp.errors = append(p.errors, msg)\n\t\treturn nil\n\t}\n\tlit.Value = value\n\treturn lit\n}\n\n\nPeekTokenは次のToken\n\ncurTokenは現在のTokenを見る\n\nちなみに 3 + 2 + 1; を動かすと\n\n[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う] called\nfunctions[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]\ncalled functions - called functionsGist262588213843476\n[https://gist.github.com/kooooohe/4da4341e2c6d2c2989859bf373874a98]BEGIN parseExpresssionStatement\n\tBEGIN parseExpresssion\n\t\tBEGIN parseIntegerLiteral\n\t\tEND parseIntegerLiteral\n\t\tBEGIN parseInfixExpression\n\t\t\tBEGIN parseExpresssion\n\t\t\t\tBEGIN parseIntegerLiteral\n\t\t\t\tEND parseIntegerLiteral\n\t\t\tEND parseExpresssion\n\t\tEND parseInfixExpression\n\t\tBEGIN parseInfixExpression\n\t\t\tBEGIN parseExpresssion\n\t\t\t\tBEGIN parseIntegerLiteral\n\t\t\t\tEND parseIntegerLiteral\n\t\t\tEND parseExpresssion\n\t\tEND parseInfixExpression\n\tEND parseExpresssion\nEND parseExpresssionStatement\n\n\nこんな順番で関数が呼ばれASTが作成される。\n\n結論から言うと、このgifの流れでASTが作成されていく\n\nでは実際に3 + 10 * 2 + 1; を解析しASTを作っていく処理の流れを見ていく。実際に関数の呼ばれる順番は以下の通りとなる\n\nparseExpression が読んでいる paseIndexExpression などが parseExpression を読んでいる点に注目してほしい。\n\n実際にどの箇所の parseExpression が呼ばれいているかこんがらがらないようにIDとして parseExpression に数値を降っておいた。\n\n以下のSlideに細かい流れは乗ってある。","html":"<h3 id=\"top-down-operator-precedence%E5%86%8D%E5%B8%B0%E4%B8%8B%E9%99%8D%E6%A7%8B%E6%96%87%E8%A7%A3%E6%9E%90-pratt-parser%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8Bexpression%E5%BC%8F%E3%81%AE%E8%A7%A3%E6%9E%90%E3%80%81ast%E6%8A%BD%E8%B1%A1%E6%A7%8B%E6%96%87%E6%9C%A8%E6%A7%8B%E7%AF%89-%E5%87%A6%E7%90%86%E3%82%92%E8%BF%BD%E3%81%86\">Top down operator precedence(再帰下降構文解析 Pratt Parser)におけるExpression(式)の解析、AST(抽象構文木)構築 処理を追う</h3><h3 id=\"go%E3%81%A7%E4%BD%9C%E3%82%8B-%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%97%E3%83%AA%E3%82%BF\">Goで作る インタプリタ</h3><figure class=\"kg-card kg-bookmark-card\"><a class=\"kg-bookmark-container\" href=\"https://www.amazon.co.jp/dp/4873118220/ref&#x3D;cm_sw_r_tw_dp_U_x_E91IDbNW6D0K4\"><div class=\"kg-bookmark-content\"><div class=\"kg-bookmark-title\">Go言語でつくるインタプリタ | Thorsten Ball, 設樂 洋爾 |本 | 通販 | Amazon</div><div class=\"kg-bookmark-description\">AmazonでThorsten Ball, 設樂 洋爾のGo言語でつくるインタプリタ。アマゾンならポイント還元本が多数。Thorsten Ball, 設樂 洋爾作品ほか、お急ぎ便対象商品は当日お届けも可能。またGo言語でつくるインタプリタもアマゾン配送商品なら通常配送無料。</div><div class=\"kg-bookmark-metadata\"><span class=\"kg-bookmark-author\">Amazon</span><span class=\"kg-bookmark-publisher\">Thorsten Ball</span></div></div><div class=\"kg-bookmark-thumbnail\"><img src=\"https://fls-fe.amazon.co.jp/1/batch/1/OP/A1VC38T7YXB528:355-7793533-7478131:899XFQE92VHK1KCJXXJ6$uedata&#x3D;s:%2Frd%2Fuedata%3Fstaticb%26id%3D899XFQE92VHK1KCJXXJ6%26pty%3DError%26spty%3DPageNotFound%26pti%3D:1000\"></div></a></figure><p></p><p>死ぬほどおすすめなので是非、</p><p>Goの基礎とTDDの基礎、簡単なデザインパターンの理解があるとよりよい。むしろそれらを知っている人にかなりおすすめの本である。</p><h4 id=\"%E3%81%93%E3%81%AE%E6%9C%AC%E3%81%AB%E5%87%BA%E3%81%A6%E3%81%8F%E3%82%8B-pratt-parser%E3%81%AB%E3%82%88%E3%82%8Bast%E3%81%AE%E6%A7%8B%E7%AF%89%E3%81%AE%E7%90%86%E8%A7%A3%E3%81%8C%E5%A4%9A%E5%B0%91%E9%9B%A3%E8%A7%A3%E3%81%AB%E6%84%9F%E3%81%98%E3%81%9F%E3%81%AE%E3%81%A7%E3%80%81%E5%87%A6%E7%90%86%E3%82%92%E5%9B%B3%E3%81%A8%E3%81%A8%E3%82%82%E3%81%AB%E8%BF%BD%E3%81%A3%E3%81%A6%E3%81%84%E3%81%93%E3%81%86%E3%81%A8%E6%80%9D%E3%81%86%E3%80%82\">この本に出てくる Pratt ParserによるASTの構築の理解が多少難解に感じたので、処理を図とともに追っていこうと思う。</h4><h3 id=\"%E5%89%8D%E6%8F%90\">前提</h3><p>lexical Analyze（字句解析）は完了している。</p><p>今回作っている言語には、</p><p>Prefix Operator(前置演算子)とInfix Operator(中置演算子)は存在し、</p><p>Postfix Operator(後置演算子）は存在しない。</p><h3 id=\"top-down-operator-precedence-%E3%81%A8%E3%81%AF\">Top down operator precedence とは?</h3><p><em>&gt;情報科学の分野において、 </em><strong><em>Prattパーサ</em></strong><em> は文法規則の代わりにトークンの意味ごとに関連付けを作るように改良された</em><a href=\"https://ja.wikipedia.org/wiki/%E5%86%8D%E5%B8%B0%E4%B8%8B%E9%99%8D%E6%A7%8B%E6%96%87%E8%A7%A3%E6%9E%90\" rel=\"noopener\"><em>再帰下降構文解析</em></a><em>のひとつ。 </em><a href=\"https://ja.wikipedia.org/wiki/Pratt%E3%83%91%E3%83%BC%E3%82%B5\" rel=\"noopener\"><em>https://ja.wikipedia.org/wiki/Prattパーサ</em></a><em> より</em></p><p>簡単に説明するとTokeのタイプごとに構文解析の関数を呼び出し、Abstruct Syntax Tree(抽象構文木)(以下 AST)を形成する</p><h3 id=\"expression-%E5%BC%8F%E3%81%A8%E3%81%AF\">Expression (式)とは</h3><p>名前の通り式のことを指す。</p><p>例: <strong>3+ 2+ 1;</strong></p><p><strong>8</strong> 単体でも式となる。</p><p>ちなみに、let x = 5 + 3 + 5;の場合は 式が 5 + 3 + 5;であり</p><p>文が let x = 5 + 3 + 5; となる。</p><h4 id=\"%E4%BB%8A%E5%9B%9E%E3%81%AEast%E3%81%AF%E3%81%93%E3%82%8C%E3%82%92-321%E3%81%A8%E8%A1%A8%E7%8F%BE%E3%81%97%E3%81%9F%E3%81%84%E3%81%AE%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82\">今回のASTはこれを ((3+2)+1)と表現したいのである。</h4><figure class=\"kg-card kg-image-card\"><img src=\"https://cdn-images-1.medium.com/max/800/1*SA7D_V7eKkzxCsF45YQhKw.png\" class=\"kg-image\" alt loading=\"lazy\"></figure><p>今回見ていく例は</p><p><strong>-3 + 10 * 2 + 1;</strong></p><p>の構文解析となる。</p><p><strong>(((-3) + (10 * 2)) + 1);を表すASTを作っていく。</strong></p><p>図式すると。</p><figure class=\"kg-card kg-image-card kg-width-wide\"><img src=\"https://cdn-images-1.medium.com/max/1200/1*eDvHceZDIDp2m1XbK8RFJg.png\" class=\"kg-image\" alt loading=\"lazy\"></figure><h3 id=\"main-codes\">Main Codes</h3><h4 id=\"precedence-%E5%84%AA%E5%85%88%E5%BA%A6\">Precedence (優先度)</h4><p>例： +(SUM)より *(PRODUCT)のほうが数値が高いので優先度が高い。</p><figure class=\"kg-card kg-bookmark-card\"><a class=\"kg-bookmark-container\" href=\"https://gist.github.com/kooooohe/4a9852c5b9c7c44dde9e1a709c7ab75b\"><div class=\"kg-bookmark-content\"><div class=\"kg-bookmark-title\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go</div><div class=\"kg-bookmark-description\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go - precedence.go</div><div class=\"kg-bookmark-metadata\"><img class=\"kg-bookmark-icon\" src=\"https://github.githubassets.com/favicons/favicon.svg\"><span class=\"kg-bookmark-author\">Gist</span><span class=\"kg-bookmark-publisher\">262588213843476</span></div></div><div class=\"kg-bookmark-thumbnail\"><img src=\"https://github.githubassets.com/images/modules/gists/gist-og-image.png\"></div></a></figure><!--kg-card-begin: markdown--><pre><code class=\"language-go\">const (\n\tLOWEST iota + 1 \n\tEQUALS          // ==\n\tLESSGRETER      // &gt; or &lt;\n\tSUM             // +\n\tPRODUCT         // *\n\tPREFIX          // -X or !X\n\tCALL            // myFunction(X)\n)\n</code></pre>\n<!--kg-card-end: markdown--><figure class=\"kg-card kg-bookmark-card\"><a class=\"kg-bookmark-container\" href=\"https://gist.github.com/kooooohe/bafc9452d3b921a586015d0ce82cb737\"><div class=\"kg-bookmark-content\"><div class=\"kg-bookmark-title\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う] token precedences</div><div class=\"kg-bookmark-description\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う] token precedences - tokenprecedences.go</div><div class=\"kg-bookmark-metadata\"><img class=\"kg-bookmark-icon\" src=\"https://github.githubassets.com/favicons/favicon.svg\"><span class=\"kg-bookmark-author\">Gist</span><span class=\"kg-bookmark-publisher\">262588213843476</span></div></div><div class=\"kg-bookmark-thumbnail\"><img src=\"https://github.githubassets.com/images/modules/gists/gist-og-image.png\"></div></a></figure><!--kg-card-begin: markdown--><pre><code class=\"language-go\">var precedences = map[token.TokenType]int{\n\ttoken.EQ:       EQUALS,\n\ttoken.NOT_EQ:   EQUALS,\n\ttoken.LT:       LESSGRETER,\n\ttoken.GT:       LESSGRETER,\n\ttoken.PLUS:     SUM,\n\ttoken.MINUS:    SUM,\n\ttoken.SLASH:    PRODUCT,\n\ttoken.ASTERISK: PRODUCT,\n}\n</code></pre>\n<!--kg-card-end: markdown--><h4 id=\"%E6%9C%80%E5%88%9D%E3%81%AB%E5%91%BC%E3%81%B0%E3%82%8C%E3%82%8B%E3%82%B3%E3%83%BC%E3%83%89\">最初に呼ばれるコード</h4><figure class=\"kg-card kg-bookmark-card kg-card-hascaption\"><a class=\"kg-bookmark-container\" href=\"https://gist.github.com/kooooohe/57fcf2b867adb0a940f8918dff385470\"><div class=\"kg-bookmark-content\"><div class=\"kg-bookmark-title\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う] parseExpressionStatement.go</div><div class=\"kg-bookmark-description\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う] parseExpressionStatement.go - parseExpressionStatement.go</div><div class=\"kg-bookmark-metadata\"><img class=\"kg-bookmark-icon\" src=\"https://github.githubassets.com/favicons/favicon.svg\"><span class=\"kg-bookmark-author\">Gist</span><span class=\"kg-bookmark-publisher\">262588213843476</span></div></div><div class=\"kg-bookmark-thumbnail\"><img src=\"https://github.githubassets.com/images/modules/gists/gist-og-image.png\"></div></a><figcaption>[</figcaption></figure><!--kg-card-begin: markdown--><pre><code class=\"language-go\">\nfunc (p *Parser) parseExpressionStatement() *ast.ExpressionStatement {\n\tstmt := &amp;ast.ExpressionStatement{Token: p.curToken}\n\n\tstmt.Expression = p.parseExpression(LOWEST)\n\n\tif p.peekTokenIs(token.SEMICOLON) {\n\t\tp.nextToken()\n\t}\n\n\treturn stmt\n}\n</code></pre>\n<!--kg-card-end: markdown--><figure class=\"kg-card kg-bookmark-card\"><a class=\"kg-bookmark-container\" href=\"https://gist.github.com/kooooohe/4ae9c18205aaa33128d65df9c5cf306c\"><div class=\"kg-bookmark-content\"><div class=\"kg-bookmark-title\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]parseExpression.go</div><div class=\"kg-bookmark-description\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]parseExpression.go - parseExpression.go</div><div class=\"kg-bookmark-metadata\"><img class=\"kg-bookmark-icon\" src=\"https://github.githubassets.com/favicons/favicon.svg\"><span class=\"kg-bookmark-author\">Gist</span><span class=\"kg-bookmark-publisher\">262588213843476</span></div></div><div class=\"kg-bookmark-thumbnail\"><img src=\"https://github.githubassets.com/images/modules/gists/gist-og-image.png\"></div></a></figure><!--kg-card-begin: markdown--><pre><code class=\"language-go\">func (p *Parser) parseExpression(precedence int) ast.Expression {\n\tprefix := p.prefixParseFns[p.curToken.Type]\n\tif prefix == nil {\n\t\tp.noPrefixParseFnError(p.curToken.Type)\n\t\treturn nil\n\t}\n\tleftExp := prefix()\n\n\tfor !p.peekTokenIs(token.SEMICOLON) &amp;&amp; precedence &lt; p.peekPrecedence() {\n\t\tinfix := p.infixParseFns[p.peekToken.Type]\n\t\tif infix == nil {\n\t\t\treturn leftExp\n\t\t}\n\n\t\tp.nextToken()\n\t\tleftExp = infix(leftExp)\n\t}\n\treturn leftExp\n}\n</code></pre>\n<!--kg-card-end: markdown--><figure class=\"kg-card kg-bookmark-card\"><a class=\"kg-bookmark-container\" href=\"https://gist.github.com/kooooohe/07c088ac44e4aaf9d6ddd184657d2cc3\"><div class=\"kg-bookmark-content\"><div class=\"kg-bookmark-title\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.goparseInfixExpression.go</div><div class=\"kg-bookmark-description\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.goparseInfixExpression.go - parseInfixExpression.go</div><div class=\"kg-bookmark-metadata\"><img class=\"kg-bookmark-icon\" src=\"https://github.githubassets.com/favicons/favicon.svg\"><span class=\"kg-bookmark-author\">Gist</span><span class=\"kg-bookmark-publisher\">262588213843476</span></div></div><div class=\"kg-bookmark-thumbnail\"><img src=\"https://github.githubassets.com/images/modules/gists/gist-og-image.png\"></div></a></figure><!--kg-card-begin: markdown--><pre><code>func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression {\n\texpression := &amp;ast.InfixExpression{\n\t\tToken:    p.curToken,\n\t\tOperator: p.curToken.Literal,\n\t\tLeft:     left,\n\t}\n\n\tprecedence := p.curPrecedence()\n\tp.nextToken()\n\texpression.Right = p.parseExpression(precedence)\n\n\treturn expression\n}\n</code></pre>\n<!--kg-card-end: markdown--><figure class=\"kg-card kg-bookmark-card\"><a class=\"kg-bookmark-container\" href=\"https://gist.github.com/kooooohe/15318939da38846f73a562affc8a00c3\"><div class=\"kg-bookmark-content\"><div class=\"kg-bookmark-title\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go parsePrefixExpression.go</div><div class=\"kg-bookmark-description\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go parsePrefixExpression.go - parsePrefixExpression.go</div><div class=\"kg-bookmark-metadata\"><img class=\"kg-bookmark-icon\" src=\"https://github.githubassets.com/favicons/favicon.svg\"><span class=\"kg-bookmark-author\">Gist</span><span class=\"kg-bookmark-publisher\">262588213843476</span></div></div><div class=\"kg-bookmark-thumbnail\"><img src=\"https://github.githubassets.com/images/modules/gists/gist-og-image.png\"></div></a></figure><!--kg-card-begin: markdown--><pre><code>func (p *Parser) parsePrefixExpression() ast.Expression {\n\texpression := &amp;ast.PrefixExpression{\n\t\tToken:    p.curToken,\n\t\tOperator: p.curToken.Literal,\n\t}\n\n\tp.nextToken()\n\n\texpression.Right = p.parseExpression(PREFIX)\n\n\treturn expression\n}\n</code></pre>\n<!--kg-card-end: markdown--><figure class=\"kg-card kg-bookmark-card\"><a class=\"kg-bookmark-container\" href=\"https://gist.github.com/kooooohe/c91d7f5f9480da4c54058846663a1962\"><div class=\"kg-bookmark-content\"><div class=\"kg-bookmark-title\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go parseIntegerLiteral.go</div><div class=\"kg-bookmark-description\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う]precedence.go parseIntegerLiteral.go - parseIntegerLiteral.go</div><div class=\"kg-bookmark-metadata\"><img class=\"kg-bookmark-icon\" src=\"https://github.githubassets.com/favicons/favicon.svg\"><span class=\"kg-bookmark-author\">Gist</span><span class=\"kg-bookmark-publisher\">262588213843476</span></div></div><div class=\"kg-bookmark-thumbnail\"><img src=\"https://github.githubassets.com/images/modules/gists/gist-og-image.png\"></div></a></figure><!--kg-card-begin: markdown--><pre><code>func (p *Parser) parseIntegerLiteral() ast.Expression {\n\tlit := &amp;ast.IntegerLiteral{Token: p.curToken}\n\n\tvalue, err := strconv.ParseInt(p.curToken.Literal, 0, 64)\n\tif err != nil {\n\t\tmsg := fmt.Sprintf(&quot;could not parse %q as integer&quot;, p.curToken.Literal)\n\t\tp.errors = append(p.errors, msg)\n\t\treturn nil\n\t}\n\tlit.Value = value\n\treturn lit\n}\n</code></pre>\n<!--kg-card-end: markdown--><p>PeekTokenは次のToken</p><p>curTokenは現在のTokenを見る</p><p>ちなみに <code>3 + 2 + 1;</code> を動かすと</p><figure class=\"kg-card kg-bookmark-card\"><a class=\"kg-bookmark-container\" href=\"https://gist.github.com/kooooohe/4da4341e2c6d2c2989859bf373874a98\"><div class=\"kg-bookmark-content\"><div class=\"kg-bookmark-title\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う] called functions</div><div class=\"kg-bookmark-description\">[Blog][TopDownOperatorPrecedence(再帰下降構文解析)におけるExpression(式)の解析処理を追う] called functions - called functions</div><div class=\"kg-bookmark-metadata\"><img class=\"kg-bookmark-icon\" src=\"https://github.githubassets.com/favicons/favicon.svg\"><span class=\"kg-bookmark-author\">Gist</span><span class=\"kg-bookmark-publisher\">262588213843476</span></div></div><div class=\"kg-bookmark-thumbnail\"><img src=\"https://github.githubassets.com/images/modules/gists/gist-og-image.png\"></div></a></figure><!--kg-card-begin: markdown--><pre><code>BEGIN parseExpresssionStatement\n\tBEGIN parseExpresssion\n\t\tBEGIN parseIntegerLiteral\n\t\tEND parseIntegerLiteral\n\t\tBEGIN parseInfixExpression\n\t\t\tBEGIN parseExpresssion\n\t\t\t\tBEGIN parseIntegerLiteral\n\t\t\t\tEND parseIntegerLiteral\n\t\t\tEND parseExpresssion\n\t\tEND parseInfixExpression\n\t\tBEGIN parseInfixExpression\n\t\t\tBEGIN parseExpresssion\n\t\t\t\tBEGIN parseIntegerLiteral\n\t\t\t\tEND parseIntegerLiteral\n\t\t\tEND parseExpresssion\n\t\tEND parseInfixExpression\n\tEND parseExpresssion\nEND parseExpresssionStatement\n</code></pre>\n<!--kg-card-end: markdown--><p>こんな順番で関数が呼ばれASTが作成される。</p><p>結論から言うと、このgifの流れでASTが作成されていく</p><figure class=\"kg-card kg-image-card\"><img src=\"https://cdn-images-1.medium.com/max/800/1*225yN9t3tAIlFl6rsUapyA.gif\" class=\"kg-image\" alt loading=\"lazy\"></figure><p>では実際に<strong>3 + 10 * 2 + 1; </strong>を解析しASTを作っていく処理の流れを見ていく。実際に関数の呼ばれる順番は以下の通りとなる</p><p><code>parseExpression</code> が読んでいる <code>paseIndexExpression</code> などが <code>parseExpression</code> を読んでいる点に注目してほしい。</p><figure class=\"kg-card kg-image-card\"><img src=\"https://cdn-images-1.medium.com/max/800/1*ml5_oyjI3goD6gSDPzkwaA.png\" class=\"kg-image\" alt loading=\"lazy\"></figure><p>実際にどの箇所の <code>parseExpression</code> が呼ばれいているかこんがらがらないようにIDとして <code>parseExpression</code> に数値を降っておいた。</p><p>以下のSlideに細かい流れは乗ってある。</p><figure class=\"kg-card kg-embed-card\"><iframe id=\"talk_frame_556716\" src=\"//speakerdeck.com/player/a367a5e9e5dd4c89a8fb4c4d0a8a9bd0\" width=\"710\" height=\"399\" style=\"border:0; padding:0; margin:0; background:transparent;\" frameborder=\"0\" allowtransparency=\"true\" allowfullscreen=\"allowfullscreen\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\"></iframe>\n</figure><p></p>","url":"https://ghost.tech.anti-pattern.co.jp/top-down-operator-precedence-zai-gui-xia-jiang-gou-wen-jie-xi-pratt-parser-niokeruexpression-shi-nojie-xi-ast-chou-xiang-gou-wen-mu-gou-zhu-chu-li-wozhui-u/","canonical_url":null,"uuid":"885117e2-e03d-4d33-9b07-0f88709104e6","page":null,"codeinjection_foot":null,"codeinjection_head":null,"codeinjection_styles":null,"comment_id":"60fa7eeb3986b000013a3a22","reading_time":6}},"pageContext":{"slug":"top-down-operator-precedence-zai-gui-xia-jiang-gou-wen-jie-xi-pratt-parser-niokeruexpression-shi-nojie-xi-ast-chou-xiang-gou-wen-mu-gou-zhu-chu-li-wozhui-u"}},
    "staticQueryHashes": ["176528973","2358152166","2561578252","2731221146","4145280475"]}