diff options
Diffstat (limited to 'usr/gri')
| -rw-r--r-- | usr/gri/pretty/Makefile | 24 | ||||
| -rw-r--r-- | usr/gri/pretty/astprinter.go | 1269 | ||||
| -rw-r--r-- | usr/gri/pretty/godoc.go | 58 | ||||
| -rw-r--r-- | usr/gri/pretty/gofmt.go | 107 | ||||
| -rw-r--r-- | usr/gri/pretty/pretty.go | 123 | ||||
| -rwxr-xr-x | usr/gri/pretty/test.sh | 4 | ||||
| -rw-r--r-- | usr/gri/pretty/untab.go | 58 | 
7 files changed, 128 insertions, 1515 deletions
| diff --git a/usr/gri/pretty/Makefile b/usr/gri/pretty/Makefile index 96f1184b9..3171a087a 100644 --- a/usr/gri/pretty/Makefile +++ b/usr/gri/pretty/Makefile @@ -4,34 +4,26 @@  include $(GOROOT)/src/Make.$(GOARCH) -all: untab godoc pretty - -untab: untab.$O -	$(LD) -o untab untab.$O +all: godoc gofmt  godoc: godoc.$O  	$(LD) -o godoc godoc.$O -pretty: pretty.$O -	$(LD) -o pretty pretty.$O +gofmt: gofmt.$O +	$(LD) -o gofmt gofmt.$O -test: pretty +test: gofmt  	./test.sh -smoketest: pretty -	./test.sh astprinter.go +smoketest: gofmt +	./test.sh $(GOROOT)/src/pkg/go/printer/printer.go  install: pretty godoc untab  	cp godoc $(HOME)/bin/godoc -	cp pretty $(HOME)/bin/pretty -	cp untab $(HOME)/bin/untab +	cp gofmt $(HOME)/bin/gofmt  clean: -	rm -f pretty untab godoc *.$O *.a 6.out *~ - -godoc.$O:	astprinter.$O - -pretty.$O:	 astprinter.$O +	rm -f godoc gofmt *.$O *.a 6.out *~  %.$O:	%.go  	$(GC) $(F) $< diff --git a/usr/gri/pretty/astprinter.go b/usr/gri/pretty/astprinter.go deleted file mode 100644 index 867a84034..000000000 --- a/usr/gri/pretty/astprinter.go +++ /dev/null @@ -1,1269 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package astPrinter - -import ( -	"flag"; -	"fmt"; -	"go/ast"; -	"go/token"; -	"io"; -	"os"; -) - - -var ( -	debug = flag.Bool("ast_debug", false, "print debugging information"); - -	// layout control -	newlines = flag.Bool("ast_newlines", false, "respect newlines in source"); -	maxnewlines = flag.Int("ast_maxnewlines", 3, "max. number of consecutive newlines"); - -	// formatting control -	optsemicolons = flag.Bool("ast_optsemicolons", false, "print optional semicolons"); -) - - -// When we don't have a position use noPos. -var noPos token.Position; - - -// ---------------------------------------------------------------------------- -// Elementary support - -func unimplemented() { -	panic("unimplemented"); -} - - -func unreachable() { -	panic("unreachable"); -} - - -func assert(pred bool) { -	if !pred { -		panic("assertion failed"); -	} -} - - -func hasExportedNames(names []*ast.Ident) bool { -	for i, name := range names { -		if name.IsExported() { -			return true; -		} -	} -	return false; -} - - -// ---------------------------------------------------------------------------- -// TokenPrinter - -// TODO This is not yet used - should fix this. - -// An implementation of a TokenPrinter may be provided when -// initializing an AST Printer. It is used to print tokens. -// -type TokenPrinter interface { -	PrintLit(w io.Writer, tok token.Token, value []byte); -	PrintIdent(w io.Writer, value string); -	PrintToken(w io.Writer, token token.Token); -	PrintComment(w io.Writer, value []byte); -} - - -type defaultPrinter struct {} - -func (p defaultPrinter) PrintLit(w io.Writer, tok token.Token, value []byte) { -	w.Write(value); -} - - -func (p defaultPrinter) PrintIdent(w io.Writer, value string) { -	fmt.Fprint(w, value); -} - - -func (p defaultPrinter) PrintToken(w io.Writer, token token.Token) { -	fmt.Fprint(w, token.String()); -} - - -func (p defaultPrinter) PrintComment(w io.Writer, value []byte) { -	w.Write(value); -} - - -// ---------------------------------------------------------------------------- -// ASTPrinter - - -// Separators - printed in a delayed fashion, depending on context. -const ( -	none = iota; -	blank; -	tab; -	comma; -	semicolon; -) - - -// Semantic states - control formatting. -const ( -	normal = iota; -	opening_scope;  // controls indentation, scope level -	closing_scope;  // controls indentation, scope level -	inside_list;  // controls extra line breaks -) - - -type Printer struct { -	// output -	text io.Writer; - -	// token printing -	tprinter TokenPrinter; - -	// formatting control -	html bool; -	full bool;  // if false, print interface only; print all otherwise - -	// comments -	comments []*ast.Comment;  // the list of unassociated comments -	cindex int;  // the current comment index -	cpos token.Position;  // the position of the next comment - -	// current state -	lastpos token.Position;  // position after last string -	level int;  // scope level -	indentation int;  // indentation level (may be different from scope level) - -	// formatting parameters -	opt_semi bool;  // // true if semicolon separator is optional in statement list -	separator int;  // pending separator -	newlines int;  // pending newlines - -	// semantic state -	state int;  // current semantic state -	laststate int;  // state for last string - -	// expression precedence -	prec int; -} - - -func (P *Printer) hasComment(pos token.Position) bool { -	return P.cpos.Offset < pos.Offset; -} - - -func (P *Printer) nextComments() { -	P.cindex++; -	if P.comments != nil && P.cindex < len(P.comments) && P.comments[P.cindex] != nil { -		P.cpos = P.comments[P.cindex].Pos(); -	} else { -		P.cpos = token.Position{1<<30, 1<<30, 1};  // infinite -	} -} - - -func (P *Printer) Init(text io.Writer, tprinter TokenPrinter, comments []*ast.Comment, html bool) { -	// writers -	P.text = text; - -	// token printing -	if tprinter != nil { -		P.tprinter = tprinter; -	} else { -		P.tprinter = defaultPrinter{}; -	} - -	// formatting control -	P.html = html; - -	// comments -	P.comments = comments; -	P.cindex = -1; -	P.nextComments(); - -	// formatting parameters & semantic state initialized correctly by default - -	// expression precedence -	P.prec = token.LowestPrec; -} - - -// ---------------------------------------------------------------------------- -// Printing support - -func (P *Printer) htmlEscape(s string) string { -	if P.html { -		var esc string; -		for i := 0; i < len(s); i++ { -			switch s[i] { -			case '<': esc = "<"; -			case '&': esc = "&"; -			default: continue; -			} -			return s[0 : i] + esc + P.htmlEscape(s[i+1 : len(s)]); -		} -	} -	return s; -} - - -// Reduce contiguous sequences of '\t' in a string to a single '\t'. -func untabify(s string) string { -	for i := 0; i < len(s); i++ { -		if s[i] == '\t' { -			j := i; -			for j < len(s) && s[j] == '\t' { -				j++; -			} -			if j-i > 1 {  // more then one tab -				return s[0 : i+1] + untabify(s[j : len(s)]); -			} -		} -	} -	return s; -} - - -func (P *Printer) Printf(format string, s ...) { -	n, err := fmt.Fprintf(P.text, format, s); -	if err != nil { -		panic("print error - exiting"); -	} -} - - -func (P *Printer) newline(n int) { -	if n > 0 { -		m := int(*maxnewlines); -		if n > m { -			n = m; -		} -		for n > 0 { -			P.Printf("\n"); -			n--; -		} -		for i := P.indentation; i > 0; i-- { -			P.Printf("\t"); -		} -	} -} - - -func (P *Printer) TaggedString(pos token.Position, tag, s, endtag string) { -	// use estimate for pos if we don't have one -	offs := pos.Offset; -	if pos.Line == 0 { -		offs = P.lastpos.Offset; -	} - -	// -------------------------------- -	// print pending separator, if any -	// - keep track of white space printed for better comment formatting -	// TODO print white space separators after potential comments and newlines -	// (currently, we may get trailing white space before a newline) -	trailing_char := 0; -	switch P.separator { -	case none:	// nothing to do -	case blank: -		P.Printf(" "); -		trailing_char = ' '; -	case tab: -		P.Printf("\t"); -		trailing_char = '\t'; -	case comma: -		P.Printf(","); -		if P.newlines == 0 { -			P.Printf(" "); -			trailing_char = ' '; -		} -	case semicolon: -		if P.level > 0 {	// no semicolons at level 0 -			P.Printf(";"); -			if P.newlines == 0 { -				P.Printf(" "); -				trailing_char = ' '; -			} -		} -	default:	panic("UNREACHABLE"); -	} -	P.separator = none; - -	// -------------------------------- -	// interleave comments, if any -	nlcount := 0; -	if P.full { -		for ; P.hasComment(pos); P.nextComments() { -			// we have a comment that comes before the string -			comment := P.comments[P.cindex]; -			ctext := string(comment.Text);  // TODO get rid of string conversion here - -			// classify comment (len(ctext) >= 2) -			//-style comment -			if nlcount > 0 || P.cpos.Offset == 0 { -				// only white space before comment on this line -				// or file starts with comment -				// - indent -				if !*newlines && P.cpos.Offset != 0 { -					nlcount = 1; -				} -				P.newline(nlcount); -				nlcount = 0; - -			} else { -				// black space before comment on this line -				if ctext[1] == '/' { -					//-style comment -					// - put in next cell unless a scope was just opened -					//   in which case we print 2 blanks (otherwise the -					//   entire scope gets indented like the next cell) -					if P.laststate == opening_scope { -						switch trailing_char { -						case ' ': P.Printf(" ");  // one space already printed -						case '\t': // do nothing -						default: P.Printf("  "); -						} -					} else { -						if trailing_char != '\t' { -							P.Printf("\t"); -						} -					} -				} else { -					/*-style comment */ -					// - print surrounded by blanks -					if trailing_char == 0 { -						P.Printf(" "); -					} -					ctext += " "; -				} -			} - -			// print comment -			if *debug { -				P.Printf("[%d]", P.cpos.Offset); -			} -			// calling untabify increases the change for idempotent output -			// since tabs in comments are also interpreted by tabwriter -			P.Printf("%s", P.htmlEscape(untabify(ctext))); -		} -		// At this point we may have nlcount > 0: In this case we found newlines -		// that were not followed by a comment. They are recognized (or not) when -		// printing newlines below. -	} - -	// -------------------------------- -	// interpret state -	// (any pending separator or comment must be printed in previous state) -	switch P.state { -	case normal: -	case opening_scope: -	case closing_scope: -		P.indentation--; -	case inside_list: -	default: -		panic("UNREACHABLE"); -	} - -	// -------------------------------- -	// print pending newlines -	if *newlines && (P.newlines > 0 || P.state == inside_list) && nlcount > P.newlines { -		// Respect additional newlines in the source, but only if we -		// enabled this feature (newlines.BVal()) and we are expecting -		// newlines (P.newlines > 0 || P.state == inside_list). -		// Otherwise - because we don't have all token positions - we -		// get funny formatting. -		P.newlines = nlcount; -	} -	nlcount = 0; -	P.newline(P.newlines); -	P.newlines = 0; - -	// -------------------------------- -	// print string -	if *debug { -		P.Printf("[%d]", pos); -	} -	P.Printf("%s%s%s", tag, P.htmlEscape(s), endtag); - -	// -------------------------------- -	// interpret state -	switch P.state { -	case normal: -	case opening_scope: -		P.level++; -		P.indentation++; -	case closing_scope: -		P.level--; -	case inside_list: -	default: -		panic("UNREACHABLE"); -	} -	P.laststate = P.state; -	P.state = none; - -	// -------------------------------- -	// done -	P.opt_semi = false; -	pos.Offset += len(s);  // rough estimate -	pos.Column += len(s);  // rough estimate -	P.lastpos = pos; -} - - -func (P *Printer) String(pos token.Position, s string) { -	P.TaggedString(pos, "", s, ""); -} - - -func (P *Printer) Token(pos token.Position, tok token.Token) { -	P.String(pos, tok.String()); -	//P.TaggedString(pos, "<b>", tok.String(), "</b>"); -} - - -func (P *Printer) Error(pos token.Position, tok token.Token, msg string) { -	fmt.Printf("\ninternal printing error: pos = %d, tok = %s, %s\n", pos.Offset, tok.String(), msg); -	panic(); -} - - -// An astPrinter implements io.Writer. -// TODO this is not yet used. -func (P *Printer) Write(p []byte) (n int, err os.Error) { -	// TODO -	// - no string conversion every time -	// - return proper results -	P.String(noPos, string(p)); -	return len(p), nil; -} - - -// ---------------------------------------------------------------------------- -// HTML support - -func (P *Printer) HtmlIdentifier(x *ast.Ident) { -	P.String(x.Pos(), x.Value); -	/* -	obj := x.Obj; -	if P.html && obj.Kind != symbolTable.NONE { -		// depending on whether we have a declaration or use, generate different html -		// - no need to htmlEscape ident -		id := utils.IntToString(obj.Id, 10); -		if x.Loc_ == obj.Pos { -			// probably the declaration of x -			P.TaggedString(x.Loc_, `<a name="id` + id + `">`, obj.Ident, `</a>`); -		} else { -			// probably not the declaration of x -			P.TaggedString(x.Loc_, `<a href="#id` + id + `">`, obj.Ident, `</a>`); -		} -	} else { -		P.String(x.Loc_, obj.Ident); -	} -	*/ -} - - -func (P *Printer) HtmlPackageName(pos token.Position, name string) { -	if P.html { -		sname := name[1 : len(name)-1];  // strip quotes  TODO do this elsewhere eventually -		// TODO CAPITAL HACK BELOW FIX THIS -		P.TaggedString(pos, `"<a href="/src/pkg/` + sname + `.go">`, sname, `</a>"`); -	} else { -		P.String(pos, name); -	} -} - - -// ---------------------------------------------------------------------------- -// Support - -func (P *Printer) Expr(x ast.Expr) - -func (P *Printer) Idents(list []*ast.Ident, full bool) int { -	n := 0; -	for i, x := range list { -		if n > 0 { -			P.Token(noPos, token.COMMA); -			P.separator = blank; -			P.state = inside_list; -		} -		if full || x.IsExported() { -			P.Expr(x); -			n++; -		} -	} -	return n; -} - - -func (P *Printer) Exprs(list []ast.Expr) { -	for i, x := range list { -		if i > 0 { -			P.Token(noPos, token.COMMA); -			P.separator = blank; -			P.state = inside_list; -		} -		P.Expr(x); -	} -} - - -func (P *Printer) Parameters(list []*ast.Field) { -	P.Token(noPos, token.LPAREN); -	if len(list) > 0 { -		for i, par := range list { -			if i > 0 { -				P.separator = comma; -			} -			n := P.Idents(par.Names, true); -			if n > 0 { -				P.separator = blank -			}; -			P.Expr(par.Type); -		} -	} -	P.Token(noPos, token.RPAREN); -} - - -// Returns the separator (semicolon or none) required if -// the type is terminating a declaration or statement. -func (P *Printer) Signature(params, result []*ast.Field) { -	P.Parameters(params); -	if result != nil { -		P.separator = blank; - -		if len(result) == 1 && result[0].Names == nil { -			// single anonymous result -			// => no parentheses needed unless it's a function type -			fld := result[0]; -			if dummy, is_ftyp := fld.Type.(*ast.FuncType); !is_ftyp { -				P.Expr(fld.Type); -				return; -			} -		} - -		P.Parameters(result); -	} -} - - -func (P *Printer) Fields(lbrace token.Position, list []*ast.Field, rbrace token.Position, is_interface bool) { -	P.state = opening_scope; -	P.separator = blank; -	P.Token(lbrace, token.LBRACE); - -	if len(list) > 0 { -		P.newlines = 1; -		for i, fld := range list { -			if i > 0 { -				P.separator = semicolon; -				P.newlines = 1; -			} -			n := P.Idents(fld.Names, P.full); -			if n > 0 { -				// at least one identifier -				P.separator = tab -			}; -			if n > 0 || len(fld.Names) == 0 { -				// at least one identifier or anonymous field -				if is_interface { -					if ftyp, is_ftyp := fld.Type.(*ast.FuncType); is_ftyp { -						P.Signature(ftyp.Params, ftyp.Results); -					} else { -						P.Expr(fld.Type); -					} -				} else { -					P.Expr(fld.Type); -					if fld.Tag != nil { -						P.separator = tab; -						P.Expr(&ast.StringList{fld.Tag}); -					} -				} -			} -		} -		P.newlines = 1; -	} - -	P.state = closing_scope; -	P.Token(rbrace, token.RBRACE); -	P.opt_semi = true; -} - - -// ---------------------------------------------------------------------------- -// Expressions - -func (P *Printer) Expr1(x ast.Expr, prec1 int) -func (P *Printer) Stmt(s ast.Stmt) - - -func (P *Printer) DoBadExpr(x *ast.BadExpr) { -	P.String(noPos, "BadExpr"); -} - - -func (P *Printer) DoIdent(x *ast.Ident) { -	P.HtmlIdentifier(x); -} - - -func (P *Printer) DoBinaryExpr(x *ast.BinaryExpr) { -	prec := x.Op.Precedence(); -	if prec < P.prec { -		P.Token(noPos, token.LPAREN); -	} -	P.Expr1(x.X, prec); -	P.separator = blank; -	P.Token(x.OpPos, x.Op); -	P.separator = blank; -	P.Expr1(x.Y, prec); -	if prec < P.prec { -		P.Token(noPos, token.RPAREN); -	} -} - - -func (P *Printer) DoKeyValueExpr(x *ast.KeyValueExpr) { -	P.Expr(x.Key); -	P.separator = blank; -	P.Token(x.Colon, token.COLON); -	P.separator = blank; -	P.Expr(x.Value); -} - - -func (P *Printer) DoStarExpr(x *ast.StarExpr) { -	P.Token(x.Pos(), token.MUL); -	P.Expr(x.X); -} - - -func (P *Printer) DoUnaryExpr(x *ast.UnaryExpr) { -	prec := token.UnaryPrec; -	if prec < P.prec { -		P.Token(noPos, token.LPAREN); -	} -	P.Token(x.Pos(), x.Op); -	if x.Op == token.RANGE { -		P.separator = blank; -	} -	P.Expr1(x.X, prec); -	if prec < P.prec { -		P.Token(noPos, token.RPAREN); -	} -} - - -func (P *Printer) DoIntLit(x *ast.IntLit) { -	// TODO get rid of string conversion here -	P.String(x.Pos(), string(x.Value)); -} - - -func (P *Printer) DoFloatLit(x *ast.FloatLit) { -	// TODO get rid of string conversion here -	P.String(x.Pos(), string(x.Value)); -} - - -func (P *Printer) DoCharLit(x *ast.CharLit) { -	// TODO get rid of string conversion here -	P.String(x.Pos(), string(x.Value)); -} - - -func (P *Printer) DoStringLit(x *ast.StringLit) { -	// TODO get rid of string conversion here -	P.String(x.Pos(), string(x.Value)); -} - - -func (P *Printer) DoStringList(x *ast.StringList) { -	for i, x := range x.Strings { -		if i > 0 { -			P.separator = blank; -		} -		P.DoStringLit(x); -	} -} - - -func (P *Printer) DoFuncType(x *ast.FuncType) - -func (P *Printer) DoFuncLit(x *ast.FuncLit) { -	P.DoFuncType(x.Type); -	P.separator = blank; -	P.Stmt(x.Body); -	P.opt_semi = false;  // BUG 6g or spec -	P.newlines = 0; -} - - -func (P *Printer) DoParenExpr(x *ast.ParenExpr) { -	P.Token(x.Pos(), token.LPAREN); -	P.Expr(x.X); -	P.Token(x.Rparen, token.RPAREN); -} - - -func (P *Printer) DoSelectorExpr(x *ast.SelectorExpr) { -	P.Expr1(x.X, token.HighestPrec); -	P.Token(noPos, token.PERIOD); -	P.Expr1(x.Sel, token.HighestPrec); -} - - -func (P *Printer) DoTypeAssertExpr(x *ast.TypeAssertExpr) { -	P.Expr1(x.X, token.HighestPrec); -	P.Token(noPos, token.PERIOD); -	P.Token(noPos, token.LPAREN); -	P.Expr(x.Type); -	P.Token(noPos, token.RPAREN); -} - - -func (P *Printer) DoIndexExpr(x *ast.IndexExpr) { -	P.Expr1(x.X, token.HighestPrec); -	P.Token(noPos, token.LBRACK); -	P.Expr(x.Index); -	if x.End != nil { -		P.Token(noPos, token.COLON); -		P.Expr(x.End); -	} -	P.Token(noPos, token.RBRACK); -} - - -func (P *Printer) DoCallExpr(x *ast.CallExpr) { -	P.Expr1(x.Fun, token.HighestPrec); -	P.Token(x.Lparen, token.LPAREN); -	P.Exprs(x.Args); -	P.Token(x.Rparen, token.RPAREN); -} - - -func (P *Printer) DoCompositeLit(x *ast.CompositeLit) { -	P.Expr1(x.Type, token.HighestPrec); -	P.Token(x.Lbrace, token.LBRACE); -	P.Exprs(x.Elts); -	P.Token(x.Rbrace, token.RBRACE); -} - - -func (P *Printer) DoEllipsis(x *ast.Ellipsis) { -	P.Token(x.Pos(), token.ELLIPSIS); -} - - -func (P *Printer) DoArrayType(x *ast.ArrayType) { -	P.Token(x.Pos(), token.LBRACK); -	if x.Len != nil { -		P.Expr(x.Len); -	} -	P.Token(noPos, token.RBRACK); -	P.Expr(x.Elt); -} - - -func (P *Printer) DoStructType(x *ast.StructType) { -	P.Token(x.Pos(), token.STRUCT); -	if x.Fields != nil { -		P.Fields(x.Lbrace, x.Fields, x.Rbrace, false); -	} -} - - -func (P *Printer) DoFuncType(x *ast.FuncType) { -	P.Token(x.Pos(), token.FUNC); -	P.Signature(x.Params, x.Results); -} - - -func (P *Printer) DoInterfaceType(x *ast.InterfaceType) { -	P.Token(x.Pos(), token.INTERFACE); -	if x.Methods != nil { -		P.Fields(x.Lbrace, x.Methods, x.Rbrace, true); -	} -} - - -func (P *Printer) DoMapType(x *ast.MapType) { -	P.Token(x.Pos(), token.MAP); -	P.separator = blank; -	P.Token(noPos, token.LBRACK); -	P.Expr(x.Key); -	P.Token(noPos, token.RBRACK); -	P.Expr(x.Value); -} - - -func (P *Printer) DoChanType(x *ast.ChanType) { -	switch x.Dir { -	case ast.SEND | ast.RECV: -		P.Token(x.Pos(), token.CHAN); -	case ast.RECV: -		P.Token(x.Pos(), token.ARROW); -		P.Token(noPos, token.CHAN); -	case ast.SEND: -		P.Token(x.Pos(), token.CHAN); -		P.separator = blank; -		P.Token(noPos, token.ARROW); -	} -	P.separator = blank; -	P.Expr(x.Value); -} - - -func (P *Printer) Expr1(x ast.Expr, prec1 int) { -	if x == nil { -		return;  // empty expression list -	} - -	saved_prec := P.prec; -	P.prec = prec1; -	x.Visit(P); -	P.prec = saved_prec; -} - - -func (P *Printer) Expr(x ast.Expr) { -	P.Expr1(x, token.LowestPrec); -} - - -// ---------------------------------------------------------------------------- -// Statements - -func (P *Printer) Stmt(s ast.Stmt) { -	s.Visit(P); -} - - -func (P *Printer) DoBadStmt(s *ast.BadStmt) { -	panic(); -} - - -func (P *Printer) Decl(d ast.Decl); - -func (P *Printer) DoDeclStmt(s *ast.DeclStmt) { -	P.Decl(s.Decl); -} - - -func (P *Printer) DoEmptyStmt(s *ast.EmptyStmt) { -	P.String(s.Pos(), ""); -} - - -func (P *Printer) DoLabeledStmt(s *ast.LabeledStmt) { -	P.indentation--; -	P.Expr(s.Label); -	P.Token(noPos, token.COLON); -	P.indentation++; -	// TODO be more clever if s.Stmt is a labeled stat as well -	P.separator = tab; -	P.Stmt(s.Stmt); -} - - -func (P *Printer) DoExprStmt(s *ast.ExprStmt) { -	P.Expr(s.X); -} - - -func (P *Printer) DoIncDecStmt(s *ast.IncDecStmt) { -	P.Expr(s.X); -	P.Token(noPos, s.Tok); -} - - -func (P *Printer) DoAssignStmt(s *ast.AssignStmt) { -	P.Exprs(s.Lhs); -	P.separator = blank; -	P.Token(s.TokPos, s.Tok); -	P.separator = blank; -	P.Exprs(s.Rhs); -} - - -func (P *Printer) DoGoStmt(s *ast.GoStmt) { -	P.Token(s.Pos(), token.GO); -	P.separator = blank; -	P.Expr(s.Call); -} - - -func (P *Printer) DoDeferStmt(s *ast.DeferStmt) { -	P.Token(s.Pos(), token.DEFER); -	P.separator = blank; -	P.Expr(s.Call); -} - - -func (P *Printer) DoReturnStmt(s *ast.ReturnStmt) { -	P.Token(s.Pos(), token.RETURN); -	P.separator = blank; -	P.Exprs(s.Results); -} - - -func (P *Printer) DoBranchStmt(s *ast.BranchStmt) { -	P.Token(s.Pos(), s.Tok); -	if s.Label != nil { -		P.separator = blank; -		P.Expr(s.Label); -	} -} - - -func (P *Printer) StatementList(list []ast.Stmt) { -	if list != nil { -		for i, s := range list { -			if i == 0 { -				P.newlines = 1; -			} else {  // i > 0 -				if !P.opt_semi || *optsemicolons { -					// semicolon is required -					P.separator = semicolon; -				} -			} -			P.Stmt(s); -			P.newlines = 1; -			P.state = inside_list; -		} -	} -} - - -/* -func (P *Printer) Block(list []ast.Stmt, indent bool) { -	P.state = opening_scope; -	P.Token(b.Pos_, b.Tok); -	if !indent { -		P.indentation--; -	} -	P.StatementList(b.List); -	if !indent { -		P.indentation++; -	} -	if !*optsemicolons { -		P.separator = none; -	} -	P.state = closing_scope; -	if b.Tok == token.LBRACE { -		P.Token(b.Rbrace, token.RBRACE); -		P.opt_semi = true; -	} else { -		P.String(noPos, "");  // process closing_scope state transition! -	} -} -*/ - - -func (P *Printer) DoBlockStmt(s *ast.BlockStmt) { -	P.state = opening_scope; -	P.Token(s.Pos(), token.LBRACE); -	P.StatementList(s.List); -	if !*optsemicolons { -		P.separator = none; -	} -	P.state = closing_scope; -	P.Token(s.Rbrace, token.RBRACE); -	P.opt_semi = true; -} - - -func (P *Printer) ControlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, post ast.Stmt) { -	P.separator = blank; -	if init == nil && post == nil { -		// no semicolons required -		if expr != nil { -			P.Expr(expr); -		} -	} else { -		// all semicolons required -		// (they are not separators, print them explicitly) -		if init != nil { -			P.Stmt(init); -			P.separator = none; -		} -		P.Token(noPos, token.SEMICOLON); -		P.separator = blank; -		if expr != nil { -			P.Expr(expr); -			P.separator = none; -		} -		if isForStmt { -			P.Token(noPos, token.SEMICOLON); -			P.separator = blank; -			if post != nil { -				P.Stmt(post); -			} -		} -	} -	P.separator = blank; -} - - -func (P *Printer) DoIfStmt(s *ast.IfStmt) { -	P.Token(s.Pos(), token.IF); -	P.ControlClause(false, s.Init, s.Cond, nil); -	P.Stmt(s.Body); -	if s.Else != nil { -		P.separator = blank; -		P.Token(noPos, token.ELSE); -		P.separator = blank; -		P.Stmt(s.Else); -	} -} - - -func (P *Printer) DoCaseClause(s *ast.CaseClause) { -	if s.Values != nil { -		P.Token(s.Pos(), token.CASE); -		P.separator = blank; -		P.Exprs(s.Values); -	} else { -		P.Token(s.Pos(), token.DEFAULT); -	} -	P.Token(s.Colon, token.COLON); -	P.indentation++; -	P.StatementList(s.Body); -	P.indentation--; -	P.newlines = 1; -} - - -func (P *Printer) DoSwitchStmt(s *ast.SwitchStmt) { -	P.Token(s.Pos(), token.SWITCH); -	P.ControlClause(false, s.Init, s.Tag, nil); -	P.Stmt(s.Body); -} - - -func (P *Printer) DoTypeCaseClause(s *ast.TypeCaseClause) { -	if s.Type != nil { -		P.Token(s.Pos(), token.CASE); -		P.separator = blank; -		P.Expr(s.Type); -	} else { -		P.Token(s.Pos(), token.DEFAULT); -	} -	P.Token(s.Colon, token.COLON); -	P.indentation++; -	P.StatementList(s.Body); -	P.indentation--; -	P.newlines = 1; -} - - -func (P *Printer) DoTypeSwitchStmt(s *ast.TypeSwitchStmt) { -	P.Token(s.Pos(), token.SWITCH); -	P.separator = blank; -	if s.Init != nil { -		P.Stmt(s.Init); -		P.separator = none; -		P.Token(noPos, token.SEMICOLON); -	} -	P.separator = blank; -	P.Stmt(s.Assign); -	P.separator = blank; -	P.Stmt(s.Body); -} - - -func (P *Printer) DoCommClause(s *ast.CommClause) { -	if s.Rhs != nil { -		P.Token(s.Pos(), token.CASE); -		P.separator = blank; -		if s.Lhs != nil { -			P.Expr(s.Lhs); -			P.separator = blank; -			P.Token(noPos, s.Tok); -			P.separator = blank; -		} -		P.Expr(s.Rhs); -	} else { -		P.Token(s.Pos(), token.DEFAULT); -	} -	P.Token(s.Colon, token.COLON); -	P.indentation++; -	P.StatementList(s.Body); -	P.indentation--; -	P.newlines = 1; -} - - -func (P *Printer) DoSelectStmt(s *ast.SelectStmt) { -	P.Token(s.Pos(), token.SELECT); -	P.separator = blank; -	P.Stmt(s.Body); -} - - -func (P *Printer) DoForStmt(s *ast.ForStmt) { -	P.Token(s.Pos(), token.FOR); -	P.ControlClause(true, s.Init, s.Cond, s.Post); -	P.Stmt(s.Body); -} - - -func (P *Printer) DoRangeStmt(s *ast.RangeStmt) { -	P.Token(s.Pos(), token.FOR); -	P.separator = blank; -	P.Expr(s.Key); -	if s.Value != nil { -		P.Token(noPos, token.COMMA); -		P.separator = blank; -		P.state = inside_list; -		P.Expr(s.Value); -	} -	P.separator = blank; -	P.Token(s.TokPos, s.Tok); -	P.separator = blank; -	P.Token(noPos, token.RANGE); -	P.separator = blank; -	P.Expr(s.X); -	P.separator = blank; -	P.Stmt(s.Body); -} - - -// ---------------------------------------------------------------------------- -// Declarations - -func (P *Printer) DoBadDecl(d *ast.BadDecl) { -	P.String(d.Pos(), "<BAD DECL>"); -} - - -func (P *Printer) importSpec(d *ast.ImportSpec) { -	if d.Name != nil { -		P.Expr(d.Name); -	} else { -		P.String(d.Path[0].Pos(), "");  // flush pending ';' separator/newlines -	} -	P.separator = tab; -	// TODO fix for longer package names -	P.HtmlPackageName(d.Path[0].Pos(), string(d.Path[0].Value)); -	P.newlines = 2; -} - - -func (P *Printer) valueSpec(d *ast.ValueSpec) { -	P.Idents(d.Names, P.full); -	if d.Type != nil { -		P.separator = blank;  // TODO switch to tab? (indentation problem with structs) -		P.Expr(d.Type); -	} -	if d.Values != nil { -		P.separator = tab; -		P.Token(noPos, token.ASSIGN); -		P.separator = blank; -		P.Exprs(d.Values); -	} -	P.newlines = 2; -} - - -func (P *Printer) typeSpec(d *ast.TypeSpec) { -	P.Expr(d.Name); -	P.separator = blank;  // TODO switch to tab? (but indentation problem with structs) -	P.Expr(d.Type); -	P.newlines = 2; -} - - -func (P *Printer) spec(d ast.Spec) { -	switch s := d.(type) { -	case *ast.ImportSpec: P.importSpec(s); -	case *ast.ValueSpec: P.valueSpec(s); -	case *ast.TypeSpec: P.typeSpec(s); -	default: panic("unreachable"); -	} -} - - -func (P *Printer) DoGenDecl(d *ast.GenDecl) { -	P.Token(d.Pos(), d.Tok); -	P.separator = blank; - -	if d.Lparen.Line > 0 { -		// group of parenthesized declarations -		P.state = opening_scope; -		P.Token(d.Lparen, token.LPAREN); -		if len(d.Specs) > 0 { -			P.newlines = 1; -			for i := 0; i < len(d.Specs); i++ { -				if i > 0 { -					P.separator = semicolon; -				} -				P.spec(d.Specs[i]); -				P.newlines = 1; -			} -		} -		P.state = closing_scope; -		P.Token(d.Rparen, token.RPAREN); -		P.opt_semi = true; -		P.newlines = 2; - -	} else { -		// single declaration -		P.spec(d.Specs[0]); -	} -} - - -func (P *Printer) DoFuncDecl(d *ast.FuncDecl) { -	P.Token(d.Pos(), token.FUNC); -	P.separator = blank; -	if recv := d.Recv; recv != nil { -		// method: print receiver -		P.Token(noPos, token.LPAREN); -		if len(recv.Names) > 0 { -			P.Expr(recv.Names[0]); -			P.separator = blank; -		} -		P.Expr(recv.Type); -		P.Token(noPos, token.RPAREN); -		P.separator = blank; -	} -	P.Expr(d.Name); -	P.Signature(d.Type.Params, d.Type.Results); -	if P.full && d.Body != nil { -		P.separator = blank; -		P.Stmt(d.Body); -	} -	P.newlines = 3; -} - - -func (P *Printer) Decl(d ast.Decl) { -	d.Visit(P); -} - - -// ---------------------------------------------------------------------------- -// Program - -func (P *Printer) DoProgram(p *ast.Program) { -	P.full = true; -	P.Token(p.Pos(), token.PACKAGE); -	P.separator = blank; -	P.Expr(p.Name); -	P.newlines = 1; -	for i := 0; i < len(p.Decls); i++ { -		P.Decl(p.Decls[i]); -	} -	P.newlines = 1; -} diff --git a/usr/gri/pretty/godoc.go b/usr/gri/pretty/godoc.go index f2d66079a..c4bc6d7e2 100644 --- a/usr/gri/pretty/godoc.go +++ b/usr/gri/pretty/godoc.go @@ -33,6 +33,7 @@ import (  	"go/ast";  	"go/doc";  	"go/parser"; +	"go/printer";  	"go/token";  	"http";  	"io"; @@ -47,8 +48,6 @@ import (  	"tabwriter";  	"template";  	"time"; - -	"astprinter";  // TODO remove eventually in favor of ast.Fprint  ) @@ -90,7 +89,6 @@ var (  	// layout control  	tabwidth = flag.Int("tabwidth", 4, "tab width"); -	usetabs = flag.Bool("tabs", false, "align with tabs instead of spaces");  	html = flag.Bool("html", false, "print HTML in command-line mode");  	// server control @@ -129,11 +127,7 @@ func isPkgDir(dir *os.Dir) bool {  func makeTabwriter(writer io.Writer) *tabwriter.Writer { -	padchar := byte(' '); -	if *usetabs { -		padchar = '\t'; -	} -	return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, tabwriter.FilterHTML); +	return tabwriter.NewWriter(writer, *tabwidth, 1, byte(' '), 0);  } @@ -203,22 +197,12 @@ func parse(path string, mode uint) (*ast.Program, *parseErrors) {  // ----------------------------------------------------------------------------  // Templates -// Return text for decl. -func DeclText(d ast.Decl) []byte { -	var buf io.ByteBuffer; -	var p astPrinter.Printer; -	p.Init(&buf, nil, nil, false); -	d.Visit(&p); -	return buf.Data(); -} - - -// Return text for expr. -func ExprText(d ast.Expr) []byte { +// Return text for an AST node. +func nodeText(node interface{}, mode uint) []byte {  	var buf io.ByteBuffer; -	var p astPrinter.Printer; -	p.Init(&buf, nil, nil, false); -	d.Visit(&p); +	tw := makeTabwriter(&buf); +	printer.Fprint(tw, node, mode); +	tw.Flush();  	return buf.Data();  } @@ -235,9 +219,9 @@ func toText(x interface{}) []byte {  	case String:  		return io.StringBytes(v.String());  	case ast.Decl: -		return DeclText(v); +		return nodeText(v, printer.ExportsOnly);  	case ast.Expr: -		return ExprText(v); +		return nodeText(v, printer.ExportsOnly);  	}  	var buf io.ByteBuffer;  	fmt.Fprint(&buf, x); @@ -247,23 +231,7 @@ func toText(x interface{}) []byte {  // Template formatter for "html" format.  func htmlFmt(w io.Writer, x interface{}, format string) { -	// Can do better than text in some cases. -	switch v := x.(type) { -	case ast.Decl: -		var p astPrinter.Printer; -		tw := makeTabwriter(w); -		p.Init(tw, nil, nil, true); -		v.Visit(&p); -		tw.Flush(); -	case ast.Expr: -		var p astPrinter.Printer; -		tw := makeTabwriter(w); -		p.Init(tw, nil, nil, true); -		v.Visit(&p); -		tw.Flush(); -	default: -		template.HtmlEscape(w, toText(x)); -	} +	template.HtmlEscape(w, toText(x));  } @@ -363,11 +331,7 @@ func serveGoSource(c *http.Conn, name string) {  	var buf io.ByteBuffer;  	fmt.Fprintln(&buf, "<pre>"); -	var p astPrinter.Printer; -	writer := makeTabwriter(&buf);  // for nicely formatted output -	p.Init(writer, nil, nil, true); -	p.DoProgram(prog); -	writer.Flush();  // ignore errors +	template.HtmlEscape(&buf, nodeText(prog, printer.DocComments));  	fmt.Fprintln(&buf, "</pre>");  	servePage(c, name + " - Go source", buf.Data()); diff --git a/usr/gri/pretty/gofmt.go b/usr/gri/pretty/gofmt.go new file mode 100644 index 000000000..73f9d8e23 --- /dev/null +++ b/usr/gri/pretty/gofmt.go @@ -0,0 +1,107 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( +	"flag"; +	"fmt"; +	"go/parser"; +	"go/printer"; +	"io"; +	"os"; +	"sort"; +	"tabwriter"; +) + + +var ( +	// operation modes +	silent = flag.Bool("s", false, "silent mode: parsing only"); +	verbose = flag.Bool("v", false, "verbose mode: trace parsing"); +	exports = flag.Bool("x", false, "show exports only"); + +	// layout control +	tabwidth = flag.Int("tabwidth", 4, "tab width"); +	usetabs = flag.Bool("tabs", false, "align with tabs instead of blanks"); +	optcommas = flag.Bool("optcommas", false, "print optional commas"); +	optsemis = flag.Bool("optsemis", false, "print optional semicolons"); +) + + +func usage() { +	fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [file.go]\n"); +	flag.PrintDefaults(); +	os.Exit(1); +} + + +func parserMode() uint { +	mode := parser.ParseComments; +	if *verbose { +		mode |= parser.Trace; +	} +	return mode; +} + + +func printerMode() uint { +	mode := uint(0); +	if *exports { +		mode |= printer.ExportsOnly; +	} +	if *optcommas { +		mode |= printer.OptCommas; +	} +	if *optsemis { +		mode |= printer.OptSemis; +	} +	return mode; +} + + +func makeTabwriter(writer io.Writer) *tabwriter.Writer { +	padchar := byte(' '); +	if *usetabs { +		padchar = '\t'; +	} +	return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, 0); +} + + +func main() { +	flag.Parse(); + +	var filename string; +	switch flag.NArg() { +	case 0: filename = "/dev/stdin"; +	case 1: filename = flag.Arg(0); +	default: usage(); +	} + +	src, err := io.ReadFile(filename); +	if err != nil { +		fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err); +		os.Exit(1); +	} + +	prog, err := parser.Parse(src, parserMode()); +	if err != nil { +		if errors, ok := err.(parser.ErrorList); ok { +			sort.Sort(errors); +			for _, e := range errors { +				fmt.Fprintf(os.Stderr, "%s:%v\n", filename, e); +			} +		} else { +			fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err); +		} +		os.Exit(1); +	} + +	if !*silent { +		w := makeTabwriter(os.Stdout); +		printer.Fprint(w, prog, printerMode()); +		w.Flush(); +	} +} diff --git a/usr/gri/pretty/pretty.go b/usr/gri/pretty/pretty.go deleted file mode 100644 index 82fc16b3c..000000000 --- a/usr/gri/pretty/pretty.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( -	"astprinter";  // TODO remove once go/printer is fully functional -	"flag"; -	"fmt"; -	"go/ast"; -	"go/parser"; -	"go/token"; -	"io"; -	"os"; -	"sort"; -	"tabwriter"; -) - - -var ( -	// operation modes -	columns bool; -	// TODO remove silent flag eventually, can achieve same by proving no format file -	silent = flag.Bool("s", false, "silent mode: no pretty print output"); -	verbose = flag.Bool("v", false, "verbose mode: trace parsing"); - -	// layout control -	format = flag.String("format", "", "format file"); -	tabwidth = flag.Int("tabwidth", 4, "tab width"); -	usetabs = flag.Bool("tabs", false, "align with tabs instead of blanks"); -) - - -func init() { -	user, err := os.Getenv("USER"); -	flag.BoolVar(&columns, "columns", user == "gri", "print column no. in error messages"); -} - - -func usage() { -	fmt.Fprintf(os.Stderr, "usage: pretty { flags } { files }\n"); -	flag.PrintDefaults(); -	os.Exit(1); -} - - -// TODO(gri) move this function into tabwriter.go? (also used in godoc) -func makeTabwriter(writer io.Writer) *tabwriter.Writer { -	padchar := byte(' '); -	if *usetabs { -		padchar = '\t'; -	} -	return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, 0); -} - - -func main() { -	// handle flags -	flag.Parse(); -	if flag.NFlag() == 0 && flag.NArg() == 0 { -		usage(); -	} - -	// initialize astFormat -	astFormat, err := ast.NewFormat(*format); -	if *format != "" && err != nil {  // ignore error if no format file given -		fmt.Fprintf(os.Stderr, "ast.NewFormat(%s): %v\n", *format, err); -		os.Exit(1); -	} - -	// determine parsing mode -	mode := parser.ParseComments; -	if *verbose { -		mode |= parser.Trace; -	} - -	// process files -	exitcode := 0; -	for i := 0; i < flag.NArg(); i++ { -		filename := flag.Arg(i); - -		src, err := io.ReadFile(filename); -		if err != nil { -			fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err); -			exitcode = 1; -			continue;  // proceed with next file -		} - -		prog, err := parser.Parse(src, mode); -		if err != nil { -			if errors, ok := err.(parser.ErrorList); ok { -				sort.Sort(errors); -				for _, e := range errors { -					fmt.Fprintf(os.Stderr, "%s:%v\n", filename, e); -				} -			} else { -				fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err); -			} -			exitcode = 1; -			continue;  // proceed with next file -		} - -		if !*silent { -			tw := makeTabwriter(os.Stdout); -			if *format != "" { -				_, err := astFormat.Fprint(tw, prog); -				if err != nil { -					fmt.Fprintf(os.Stderr, "format error: %v\n", err); -					exitcode = 1; -					continue;  // proceed with next file -				} -			} else { -				var p astPrinter.Printer; -				p.Init(tw, nil, nil /*prog.Comments*/, false); -				p.DoProgram(prog); -			} -			tw.Flush(); -		} -	} - -	os.Exit(exitcode); -} diff --git a/usr/gri/pretty/test.sh b/usr/gri/pretty/test.sh index c33082115..4015b0c8e 100755 --- a/usr/gri/pretty/test.sh +++ b/usr/gri/pretty/test.sh @@ -10,7 +10,7 @@ if [ -z "$O" ]; then  	exit 1  fi -CMD="./pretty -format=ast.txt" +CMD="./gofmt"  TMP1=test_tmp1.go  TMP2=test_tmp2.go  TMP3=test_tmp3.go @@ -34,7 +34,7 @@ apply1() {  	# the following have semantic errors: bug039.go | bug040.go  	test_errors.go | calc.go | method1.go | selftest1.go | func3.go | const2.go | \  	bug014.go | bug025.go | bug029.go | bug032.go | bug039.go | bug040.go | bug050.go |  bug068.go | \ -	bug088.go | bug083.go | bug106.go | bug121.go | bug125.go | bug126.go | bug132.go | bug133.go | bug134.go ) ;; +	bug088.go | bug083.go | bug106.go | bug121.go | bug125.go | bug126.go | bug132.go | bug133.go | bug134.go | bug160.go ) ;;  	* ) $1 $2; count $F;;  	esac  } diff --git a/usr/gri/pretty/untab.go b/usr/gri/pretty/untab.go deleted file mode 100644 index b18e08f8b..000000000 --- a/usr/gri/pretty/untab.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2009 The Go Authors.  All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( -	"flag"; -	"fmt"; -	"io"; -	"os"; -	"tabwriter"; -) - - -var ( -	tabwidth = flag.Int("tabwidth", 4, "tab width"); -	usetabs = flag.Bool("usetabs", false, "align with tabs instead of blanks"); -) - - -func error(format string, params ...) { -	fmt.Printf(format, params); -	os.Exit(1); -} - - -func untab(name string, src *os.File, dst *tabwriter.Writer) { -	n, err := io.Copy(src, dst); -	if err != nil { -		error("error while processing %s (%v)", name, err); -	} -	//dst.Flush(); -} - - -func main() { -	flag.Parse(); -	padchar := byte(' '); -	if *usetabs { -		padchar = '\t'; -	} -	dst := tabwriter.NewWriter(os.Stdout, *tabwidth, 1, padchar, 0); -	if flag.NArg() > 0 { -		for i := 0; i < flag.NArg(); i++ { -			name := flag.Arg(i); -			src, err := os.Open(name, os.O_RDONLY, 0); -			if err != nil { -				error("could not open %s (%v)\n", name, err); -			} -			untab(name, src, dst); -			src.Close();  // ignore errors -		} -	} else { -		// no files => use stdin -		untab("/dev/stdin", os.Stdin, dst); -	} -} | 
