github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/compiler/ast/printer/tree_printer.go (about)

     1  package printer
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"reflect"
     7  	"strings"
     8  
     9  	"github.com/hirochachacha/plua/compiler/ast"
    10  	"github.com/hirochachacha/plua/internal/strconv"
    11  )
    12  
    13  const treeIndent = "  "
    14  
    15  type treeprinter struct {
    16  	w   io.Writer
    17  	err error
    18  }
    19  
    20  func (p treeprinter) printf(s string, args ...interface{}) {
    21  	if p.err != nil {
    22  		return
    23  	}
    24  	_, p.err = fmt.Fprintf(p.w, s, args...)
    25  }
    26  
    27  func (p treeprinter) printNode(node ast.Node, prefix string, depth int) {
    28  	if p.err != nil {
    29  		return
    30  	}
    31  
    32  	ind := strings.Repeat(treeIndent, depth)
    33  	nind := ind + treeIndent
    34  
    35  	if reflect.ValueOf(node).IsNil() {
    36  		p.printf("%snil\n", prefix)
    37  
    38  		return
    39  	}
    40  
    41  	switch node := node.(type) {
    42  	case *ast.Comment:
    43  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
    44  		p.printf("%sHyphen: %s\n", nind, node.Hyphen)
    45  		p.printf("%sText: %s\n", nind, strconv.Quote(node.Text))
    46  		p.printf("%s}\n", ind)
    47  	case *ast.CommentGroup:
    48  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
    49  		p.printf("%sList: {\n", nind)
    50  		for _, e := range node.List {
    51  			p.printNode(e, nind+treeIndent, depth+2)
    52  		}
    53  		p.printf("%s}\n", nind)
    54  		p.printf("%s}\n", ind)
    55  	case *ast.ParamList:
    56  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
    57  		p.printf("%sLparen: %s\n", nind, node.Lparen)
    58  		p.printf("%sList: {\n", nind)
    59  		for _, e := range node.List {
    60  			p.printNode(e, nind+treeIndent, depth+2)
    61  		}
    62  		p.printf("%s}\n", nind)
    63  		p.printf("%sEllipsis: %s\n", nind, node.Ellipsis)
    64  		p.printf("%sRparen: %s\n", nind, node.Rparen)
    65  		p.printf("%s}\n", ind)
    66  
    67  	case *ast.BadExpr:
    68  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
    69  		p.printf("%sFrom: %s\n", nind, node.From)
    70  		p.printf("%sTo: %s\n", nind, node.To)
    71  		p.printf("%s}\n", ind)
    72  	case *ast.Name:
    73  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
    74  		p.printf("%sNamePos: %s\n", nind, node.NamePos)
    75  		p.printf("%sName: %s\n", nind, node.Name)
    76  		// p.printf("%sIsLHS: %t\n", nind, node.IsLHS)
    77  		p.printf("%s}\n", ind)
    78  	case *ast.Vararg:
    79  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
    80  		p.printf("%sEllipsis: %s\n", nind, node.Ellipsis)
    81  		p.printf("%s}\n", ind)
    82  	case *ast.BasicLit:
    83  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
    84  		p.printf("%sToken.Type: %s\n", nind, node.Token.Type)
    85  		p.printf("%sToken.Pos: %s\n", nind, node.Token.Pos)
    86  		p.printf("%sToken.Lit: %s\n", nind, node.Token.Lit)
    87  		p.printf("%s}\n", ind)
    88  	case *ast.FuncLit:
    89  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
    90  		p.printf("%sFunc: %s\n", nind, node.Func)
    91  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
    92  		p.printf("%sEndPos: %s\n", nind, node.EndPos)
    93  		p.printf("%s}\n", ind)
    94  	case *ast.TableLit:
    95  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
    96  		p.printf("%sLbrace: %s\n", nind, node.Lbrace)
    97  		p.printf("%sFields: {\n", nind)
    98  		for _, e := range node.Fields {
    99  			p.printNode(e, nind+treeIndent, depth+2)
   100  		}
   101  		p.printf("%s}\n", nind)
   102  		p.printf("%sRbrace: %s\n", nind, node.Rbrace)
   103  		p.printf("%s}\n", ind)
   104  	case *ast.ParenExpr:
   105  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   106  		p.printf("%sLparen: %s\n", nind, node.Lparen)
   107  		p.printNode(node.X, fmt.Sprintf("%sX: ", nind), depth+1)
   108  		p.printf("%sRparen: %s\n", nind, node.Rparen)
   109  		p.printf("%s}\n", ind)
   110  	case *ast.SelectorExpr:
   111  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   112  		p.printNode(node.X, fmt.Sprintf("%sX: ", nind), depth+1)
   113  		p.printNode(node.Sel, fmt.Sprintf("%sSel: ", nind), depth+1)
   114  		// p.printf("%sIsLHS: %t\n", nind, node.IsLHS)
   115  		p.printf("%s}\n", ind)
   116  	case *ast.IndexExpr:
   117  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   118  		p.printNode(node.X, fmt.Sprintf("%sX: ", nind), depth+1)
   119  		p.printf("%sLbrack: %s\n", nind, node.Lbrack)
   120  		p.printNode(node.Index, fmt.Sprintf("%sIndex: ", nind), depth+1)
   121  		p.printf("%sRbrack: %s\n", nind, node.Rbrack)
   122  		// p.printf("%sIsLHS: %t\n", nind, node.IsLHS)
   123  		p.printf("%s}\n", ind)
   124  	case *ast.CallExpr:
   125  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   126  		p.printNode(node.X, fmt.Sprintf("%sX: ", nind), depth+1)
   127  		p.printf("%sColon: %s\n", nind, node.Colon)
   128  		p.printNode(node.Name, fmt.Sprintf("%sName: ", nind), depth+1)
   129  		p.printf("%sLparen: %s\n", nind, node.Lparen)
   130  		p.printf("%sArgs: {\n", nind)
   131  		for _, e := range node.Args {
   132  			p.printNode(e, nind+treeIndent, depth+2)
   133  		}
   134  		p.printf("%s}\n", nind)
   135  		p.printf("%sRparen: %s\n", nind, node.Rparen)
   136  		p.printf("%s}\n", ind)
   137  	case *ast.UnaryExpr:
   138  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   139  		p.printf("%sOpPos: %s\n", nind, node.OpPos)
   140  		p.printf("%sOp: %s\n", nind, node.Op)
   141  		p.printNode(node.X, fmt.Sprintf("%sX: ", nind), depth+1)
   142  		p.printf("%s}\n", ind)
   143  	case *ast.BinaryExpr:
   144  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   145  		p.printNode(node.X, fmt.Sprintf("%sX: ", nind), depth+1)
   146  		p.printf("%sOpPos: %s\n", nind, node.OpPos)
   147  		p.printf("%sOp: %s\n", nind, node.Op)
   148  		p.printNode(node.Y, fmt.Sprintf("%sY: ", nind), depth+1)
   149  		p.printf("%s}\n", ind)
   150  	case *ast.KeyValueExpr:
   151  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   152  		p.printf("%sLbrack: %s\n", nind, node.Lbrack)
   153  		p.printNode(node.Key, fmt.Sprintf("%sKey: ", nind), depth+1)
   154  		p.printf("%sRbrack: %s\n", nind, node.Rbrack)
   155  		p.printf("%sEqual: %s\n", nind, node.Equal)
   156  		p.printNode(node.Value, fmt.Sprintf("%sValue: ", nind), depth+1)
   157  		p.printf("%s}\n", ind)
   158  
   159  	case *ast.BadStmt:
   160  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   161  		p.printf("%sFrom: %s\n", nind, node.From)
   162  		p.printf("%sTo: %s\n", nind, node.To)
   163  		p.printf("%s}\n", ind)
   164  	case *ast.EmptyStmt:
   165  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   166  		p.printf("%sSemicolon: %s\n", nind, node.Semicolon)
   167  		p.printf("%s}\n", ind)
   168  	case *ast.LocalAssignStmt:
   169  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   170  		p.printf("%sLHS: {\n", nind)
   171  		for _, e := range node.LHS {
   172  			p.printNode(e, nind+treeIndent, depth+2)
   173  		}
   174  		p.printf("%s}\n", nind)
   175  		p.printf("%sEqual: %s\n", nind, node.Equal)
   176  		p.printf("%sRHS: {\n", nind)
   177  		for _, e := range node.RHS {
   178  			p.printNode(e, nind+treeIndent, depth+2)
   179  		}
   180  		p.printf("%s}\n", nind)
   181  		p.printf("%s}\n", ind)
   182  	case *ast.LocalFuncStmt:
   183  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   184  		p.printf("%sLocal: %s\n", nind, node.Local)
   185  		p.printf("%sFunc: %s\n", nind, node.Func)
   186  		p.printNode(node.Name, fmt.Sprintf("%sName: ", nind), depth+1)
   187  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
   188  		p.printf("%sEndPos: %s\n", nind, node.EndPos)
   189  		p.printf("%s}\n", ind)
   190  	case *ast.FuncStmt:
   191  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   192  		p.printf("%sFunc: %s\n", nind, node.Func)
   193  		p.printf("%sPathList: {\n", nind)
   194  		for _, e := range node.PathList {
   195  			p.printNode(e, nind+treeIndent, depth+2)
   196  		}
   197  		p.printf("%s}\n", nind)
   198  		p.printNode(node.Name, fmt.Sprintf("%sName: ", nind), depth+1)
   199  		p.printf("%sAccessTok: '%s'\n", nind, node.AccessTok)
   200  		p.printf("%sAccessPos: %s\n", nind, node.AccessPos)
   201  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
   202  		p.printf("%sEndPos: %s\n", nind, node.EndPos)
   203  		p.printf("%s}\n", ind)
   204  	case *ast.LabelStmt:
   205  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   206  		p.printf("%sLabel: %s\n", nind, node.Label)
   207  		p.printNode(node.Name, fmt.Sprintf("%sName: ", nind), depth+1)
   208  		p.printf("%sEndLabel: %s\n", nind, node.EndLabel)
   209  		p.printf("%s}\n", ind)
   210  	case *ast.ExprStmt:
   211  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   212  		p.printNode(node.X, fmt.Sprintf("%sX: ", nind), depth+1)
   213  		p.printf("%s}\n", ind)
   214  	case *ast.AssignStmt:
   215  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   216  		p.printf("%sLHS: {\n", nind)
   217  		for _, e := range node.LHS {
   218  			p.printNode(e, nind+treeIndent, depth+2)
   219  		}
   220  		p.printf("%s}\n", nind)
   221  		p.printf("%sEqual: %s\n", nind, node.Equal)
   222  		p.printf("%sRHS: {\n", nind)
   223  		for _, e := range node.RHS {
   224  			p.printNode(e, nind+treeIndent, depth+2)
   225  		}
   226  		p.printf("%s}\n", nind)
   227  		p.printf("%s}\n", ind)
   228  	case *ast.GotoStmt:
   229  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   230  		p.printf("%sGoto: %s\n", nind, node.Goto)
   231  		p.printNode(node.Label, fmt.Sprintf("%sLabel: ", nind), depth+1)
   232  		p.printf("%s}\n", ind)
   233  	case *ast.BreakStmt:
   234  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   235  		p.printf("%sBreak: %s\n", nind, node.Break)
   236  		p.printf("%s}\n", ind)
   237  	case *ast.IfStmt:
   238  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   239  		p.printf("%sIf: %s\n", nind, node.If)
   240  		p.printNode(node.Cond, fmt.Sprintf("%sCond: ", nind), depth+1)
   241  		p.printf("%sThen: %s\n", nind, node.Then)
   242  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
   243  		p.printf("%sElseIfList: {\n", nind)
   244  		for _, e := range node.ElseIfList {
   245  			p.printf("%sElseIf: %s\n", nind+treeIndent, e.If)
   246  			p.printNode(e.Cond, fmt.Sprintf("%sCond: ", nind+treeIndent), depth+2)
   247  			p.printf("%sThen: %s\n", nind+treeIndent, e.Then)
   248  			p.printNode(e.Body, fmt.Sprintf("%sBody: ", nind+treeIndent), depth+2)
   249  		}
   250  		p.printf("%s}\n", nind)
   251  		p.printf("%sElse: %s\n", nind, node.Else)
   252  		p.printNode(node.ElseBody, fmt.Sprintf("%sElseBody: ", nind), depth+1)
   253  		p.printf("%sEndPos: %s\n", nind, node.EndPos)
   254  		p.printf("%s}\n", ind)
   255  	case *ast.DoStmt:
   256  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   257  		p.printf("%sDo: %s\n", nind, node.Do)
   258  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
   259  		p.printf("%sEndPos: %s\n", nind, node.EndPos)
   260  		p.printf("%s}\n", ind)
   261  	case *ast.WhileStmt:
   262  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   263  		p.printf("%sWhile: %s\n", nind, node.While)
   264  		p.printNode(node.Cond, fmt.Sprintf("%sCond: ", nind), depth+1)
   265  		p.printf("%sDo: %s\n", nind, node.Do)
   266  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
   267  		p.printf("%sEndPos: %s\n", nind, node.EndPos)
   268  		p.printf("%s}\n", ind)
   269  	case *ast.RepeatStmt:
   270  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   271  		p.printf("%sRepeat: %s\n", nind, node.Repeat)
   272  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
   273  		p.printf("%sUntil: %s\n", nind, node.Until)
   274  		p.printNode(node.Cond, fmt.Sprintf("%sCond: ", nind), depth+1)
   275  		p.printf("%s}\n", ind)
   276  	case *ast.ReturnStmt:
   277  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   278  		p.printf("%sReturn: %s\n", nind, node.Return)
   279  		p.printf("%sResults: {\n", nind)
   280  		for _, e := range node.Results {
   281  			p.printNode(e, nind+treeIndent, depth+2)
   282  		}
   283  		p.printf("%s}\n", nind)
   284  		p.printf("%s}\n", ind)
   285  	case *ast.ForStmt:
   286  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   287  		p.printf("%sFor: %s\n", nind, node.For)
   288  		p.printNode(node.Name, fmt.Sprintf("%sName: ", nind), depth+1)
   289  		p.printf("%sEqual: %s\n", nind, node.Equal)
   290  		p.printNode(node.Start, fmt.Sprintf("%sStart: ", nind), depth+1)
   291  		p.printNode(node.Finish, fmt.Sprintf("%sFinish: ", nind), depth+1)
   292  		p.printNode(node.Step, fmt.Sprintf("%sStep: ", nind), depth+1)
   293  		p.printf("%sDo: %s\n", nind, node.Do)
   294  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
   295  		p.printf("%sEndPos: %s\n", nind, node.EndPos)
   296  		p.printf("%s}\n", ind)
   297  	case *ast.ForEachStmt:
   298  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   299  		p.printf("%sFor: %s\n", nind, node.For)
   300  		p.printf("%sNames: {\n", nind)
   301  		for _, e := range node.Names {
   302  			p.printNode(e, nind+treeIndent, depth+2)
   303  		}
   304  		p.printf("%s}\n", nind)
   305  		p.printf("%sIn: %s\n", nind, node.In)
   306  		p.printf("%sExprs: {\n", nind)
   307  		for _, e := range node.Exprs {
   308  			p.printNode(e, nind+treeIndent, depth+2)
   309  		}
   310  		p.printf("%s}\n", nind)
   311  		p.printf("%sDo: %s\n", nind, node.Do)
   312  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
   313  		p.printf("%sEndPos: %s\n", nind, node.EndPos)
   314  		p.printf("%s}\n", ind)
   315  	case *ast.File:
   316  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   317  		p.printf("%sShebang: %s\n", nind, strconv.Quote(node.Shebang))
   318  		p.printf("%sChunk: {\n", nind)
   319  		for _, e := range node.Chunk {
   320  			p.printNode(e, nind+treeIndent, depth+2)
   321  		}
   322  		p.printf("%s}\n", nind)
   323  		p.printf("%sComments: {\n", nind)
   324  		for _, e := range node.Comments {
   325  			p.printNode(e, nind+treeIndent, depth+2)
   326  		}
   327  		p.printf("%s}\n", nind)
   328  		p.printf("%s}\n", ind)
   329  	case *ast.Block:
   330  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   331  		p.printf("%sOpening: %s\n", nind, node.Opening)
   332  		p.printf("%sList: {\n", nind)
   333  		for _, e := range node.List {
   334  			p.printNode(e, nind+treeIndent, depth+2)
   335  		}
   336  		p.printf("%s}\n", nind)
   337  		p.printf("%sClosing: %s\n", nind, node.Closing)
   338  		p.printf("%s}\n", ind)
   339  	case *ast.FuncBody:
   340  		p.printf("%s%s { %s-%s\n", prefix, node.Type(), node.Pos(), node.End())
   341  		p.printNode(node.Params, fmt.Sprintf("%sParams: ", nind), depth+1)
   342  		p.printNode(node.Body, fmt.Sprintf("%sBody: ", nind), depth+1)
   343  		p.printf("%s}\n", ind)
   344  	default:
   345  		panic("unreachable")
   346  	}
   347  }