1
0
mirror of https://github.com/golang/go synced 2024-11-26 05:27:57 -07:00

daily snapshot:

- adjustments to match new ast/parser interface
- removed printer.go; functionality now in astprinter.go and docprinter.go
  (more cleanups pending)
- enabled new doc printing in gds
  (lots of fine tuning missing, but pieces falling into place; e.g. methods
  associated with types. Consts, Vars, to come. Collection of all files
  belonging to a package to come)

R=r
OCL=26970
CL=26972
This commit is contained in:
Robert Griesemer 2009-03-31 16:53:58 -07:00
parent 07513c2599
commit 8f628f4955
10 changed files with 336 additions and 3620 deletions

View File

@ -28,11 +28,11 @@ install: pretty
clean: clean:
rm -f pretty *.6 *.a *~ rm -f pretty *.6 *.a *~
gds.6: utils.6 platform.6 compilation.6 printer.6 docprinter.6 astprinter.6 gds.6: utils.6 platform.6 compilation.6 docprinter.6
pretty.6: platform.6 printer.6 compilation.6 pretty.6: platform.6 ast.6 astprinter.6 compilation.6
compilation.6: platform.6 parser.6 ast.6 typechecker.6 compilation.6: platform.6 ast.6 typechecker.6
typechecker.6: ast.6 typechecker.6: ast.6
@ -40,12 +40,8 @@ ast.6: symboltable.6
symboltable.6: symboltable.6:
parser.6: ast.6 symboltable.6
platform.6: utils.6 platform.6: utils.6
printer.6: utils.6 ast.6 symboltable.6 template.6
astprinter.6: utils.6 ast.6 symboltable.6 template.6 astprinter.6: utils.6 ast.6 symboltable.6 template.6
docprinter.6: ast.6 astprinter.6 template.6 docprinter.6: ast.6 astprinter.6 template.6

View File

@ -5,7 +5,6 @@
package astPrinter package astPrinter
import ( import (
"os";
"io"; "io";
"vector"; "vector";
"tabwriter"; "tabwriter";
@ -35,9 +34,8 @@ var (
) )
// When we don't have a position use nopos. // When we don't have a position use noPos.
// TODO make sure we always have a position. var noPos token.Position;
var nopos token.Position;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -448,7 +446,7 @@ func (P *Printer) Idents(list []*ast.Ident, full bool) int {
n := 0; n := 0;
for i, x := range list { for i, x := range list {
if n > 0 { if n > 0 {
P.Token(nopos, token.COMMA); P.Token(noPos, token.COMMA);
P.separator = blank; P.separator = blank;
P.state = inside_list; P.state = inside_list;
} }
@ -464,7 +462,7 @@ func (P *Printer) Idents(list []*ast.Ident, full bool) int {
func (P *Printer) Exprs(list []ast.Expr) { func (P *Printer) Exprs(list []ast.Expr) {
for i, x := range list { for i, x := range list {
if i > 0 { if i > 0 {
P.Token(nopos, token.COMMA); P.Token(noPos, token.COMMA);
P.separator = blank; P.separator = blank;
P.state = inside_list; P.state = inside_list;
} }
@ -474,7 +472,7 @@ func (P *Printer) Exprs(list []ast.Expr) {
func (P *Printer) Parameters(list []*ast.Field) { func (P *Printer) Parameters(list []*ast.Field) {
P.Token(nopos, token.LPAREN); P.Token(noPos, token.LPAREN);
if len(list) > 0 { if len(list) > 0 {
for i, par := range list { for i, par := range list {
if i > 0 { if i > 0 {
@ -487,7 +485,7 @@ func (P *Printer) Parameters(list []*ast.Field) {
P.Expr(par.Type); P.Expr(par.Type);
} }
} }
P.Token(nopos, token.RPAREN); P.Token(noPos, token.RPAREN);
} }
@ -502,7 +500,7 @@ func (P *Printer) Signature(params, result []*ast.Field) {
// single anonymous result // single anonymous result
// => no parentheses needed unless it's a function type // => no parentheses needed unless it's a function type
fld := result[0]; fld := result[0];
if dummy, is_ftyp := fld.Type.(*ast.FunctionType); !is_ftyp { if dummy, is_ftyp := fld.Type.(*ast.FuncType); !is_ftyp {
P.Expr(fld.Type); P.Expr(fld.Type);
return; return;
} }
@ -533,7 +531,7 @@ func (P *Printer) Fields(lbrace token.Position, list []*ast.Field, rbrace token.
if n > 0 || len(fld.Names) == 0 { if n > 0 || len(fld.Names) == 0 {
// at least one identifier or anonymous field // at least one identifier or anonymous field
if is_interface { if is_interface {
if ftyp, is_ftyp := fld.Type.(*ast.FunctionType); is_ftyp { if ftyp, is_ftyp := fld.Type.(*ast.FuncType); is_ftyp {
P.Signature(ftyp.Params, ftyp.Results); P.Signature(ftyp.Params, ftyp.Results);
} else { } else {
P.Expr(fld.Type); P.Expr(fld.Type);
@ -564,7 +562,7 @@ func (P *Printer) Stmt(s ast.Stmt)
func (P *Printer) DoBadExpr(x *ast.BadExpr) { func (P *Printer) DoBadExpr(x *ast.BadExpr) {
P.String(nopos, "BadExpr"); P.String(noPos, "BadExpr");
} }
@ -576,7 +574,7 @@ func (P *Printer) DoIdent(x *ast.Ident) {
func (P *Printer) DoBinaryExpr(x *ast.BinaryExpr) { func (P *Printer) DoBinaryExpr(x *ast.BinaryExpr) {
prec := x.Op.Precedence(); prec := x.Op.Precedence();
if prec < P.prec { if prec < P.prec {
P.Token(nopos, token.LPAREN); P.Token(noPos, token.LPAREN);
} }
P.Expr1(x.X, prec); P.Expr1(x.X, prec);
P.separator = blank; P.separator = blank;
@ -584,7 +582,7 @@ func (P *Printer) DoBinaryExpr(x *ast.BinaryExpr) {
P.separator = blank; P.separator = blank;
P.Expr1(x.Y, prec); P.Expr1(x.Y, prec);
if prec < P.prec { if prec < P.prec {
P.Token(nopos, token.RPAREN); P.Token(noPos, token.RPAREN);
} }
} }
@ -607,7 +605,7 @@ func (P *Printer) DoStarExpr(x *ast.StarExpr) {
func (P *Printer) DoUnaryExpr(x *ast.UnaryExpr) { func (P *Printer) DoUnaryExpr(x *ast.UnaryExpr) {
prec := token.UnaryPrec; prec := token.UnaryPrec;
if prec < P.prec { if prec < P.prec {
P.Token(nopos, token.LPAREN); P.Token(noPos, token.LPAREN);
} }
P.Token(x.Pos(), x.Op); P.Token(x.Pos(), x.Op);
if x.Op == token.RANGE { if x.Op == token.RANGE {
@ -615,7 +613,7 @@ func (P *Printer) DoUnaryExpr(x *ast.UnaryExpr) {
} }
P.Expr1(x.X, prec); P.Expr1(x.X, prec);
if prec < P.prec { if prec < P.prec {
P.Token(nopos, token.RPAREN); P.Token(noPos, token.RPAREN);
} }
} }
@ -654,10 +652,10 @@ func (P *Printer) DoStringList(x *ast.StringList) {
} }
func (P *Printer) DoFunctionType(x *ast.FunctionType) func (P *Printer) DoFuncType(x *ast.FuncType)
func (P *Printer) DoFunctionLit(x *ast.FunctionLit) { func (P *Printer) DoFuncLit(x *ast.FuncLit) {
P.DoFunctionType(x.Type); P.DoFuncType(x.Type);
P.separator = blank; P.separator = blank;
P.Stmt(x.Body); P.Stmt(x.Body);
P.newlines = 0; P.newlines = 0;
@ -673,35 +671,35 @@ func (P *Printer) DoParenExpr(x *ast.ParenExpr) {
func (P *Printer) DoSelectorExpr(x *ast.SelectorExpr) { func (P *Printer) DoSelectorExpr(x *ast.SelectorExpr) {
P.Expr1(x.X, token.HighestPrec); P.Expr1(x.X, token.HighestPrec);
P.Token(nopos, token.PERIOD); P.Token(noPos, token.PERIOD);
P.Expr1(x.Sel, token.HighestPrec); P.Expr1(x.Sel, token.HighestPrec);
} }
func (P *Printer) DoTypeAssertExpr(x *ast.TypeAssertExpr) { func (P *Printer) DoTypeAssertExpr(x *ast.TypeAssertExpr) {
P.Expr1(x.X, token.HighestPrec); P.Expr1(x.X, token.HighestPrec);
P.Token(nopos, token.PERIOD); P.Token(noPos, token.PERIOD);
P.Token(nopos, token.LPAREN); P.Token(noPos, token.LPAREN);
P.Expr(x.Type); P.Expr(x.Type);
P.Token(nopos, token.RPAREN); P.Token(noPos, token.RPAREN);
} }
func (P *Printer) DoIndexExpr(x *ast.IndexExpr) { func (P *Printer) DoIndexExpr(x *ast.IndexExpr) {
P.Expr1(x.X, token.HighestPrec); P.Expr1(x.X, token.HighestPrec);
P.Token(nopos, token.LBRACK); P.Token(noPos, token.LBRACK);
P.Expr(x.Index); P.Expr(x.Index);
P.Token(nopos, token.RBRACK); P.Token(noPos, token.RBRACK);
} }
func (P *Printer) DoSliceExpr(x *ast.SliceExpr) { func (P *Printer) DoSliceExpr(x *ast.SliceExpr) {
P.Expr1(x.X, token.HighestPrec); P.Expr1(x.X, token.HighestPrec);
P.Token(nopos, token.LBRACK); P.Token(noPos, token.LBRACK);
P.Expr(x.Begin); P.Expr(x.Begin);
P.Token(nopos, token.COLON); P.Token(noPos, token.COLON);
P.Expr(x.End); P.Expr(x.End);
P.Token(nopos, token.RBRACK); P.Token(noPos, token.RBRACK);
} }
@ -729,14 +727,14 @@ func (P *Printer) DoEllipsis(x *ast.Ellipsis) {
func (P *Printer) DoArrayType(x *ast.ArrayType) { func (P *Printer) DoArrayType(x *ast.ArrayType) {
P.Token(x.Pos(), token.LBRACK); P.Token(x.Pos(), token.LBRACK);
P.Expr(x.Len); P.Expr(x.Len);
P.Token(nopos, token.RBRACK); P.Token(noPos, token.RBRACK);
P.Expr(x.Elt); P.Expr(x.Elt);
} }
func (P *Printer) DoSliceType(x *ast.SliceType) { func (P *Printer) DoSliceType(x *ast.SliceType) {
P.Token(x.Pos(), token.LBRACK); P.Token(x.Pos(), token.LBRACK);
P.Token(nopos, token.RBRACK); P.Token(noPos, token.RBRACK);
P.Expr(x.Elt); P.Expr(x.Elt);
} }
@ -749,7 +747,7 @@ func (P *Printer) DoStructType(x *ast.StructType) {
} }
func (P *Printer) DoFunctionType(x *ast.FunctionType) { func (P *Printer) DoFuncType(x *ast.FuncType) {
P.Token(x.Pos(), token.FUNC); P.Token(x.Pos(), token.FUNC);
P.Signature(x.Params, x.Results); P.Signature(x.Params, x.Results);
} }
@ -766,24 +764,24 @@ func (P *Printer) DoInterfaceType(x *ast.InterfaceType) {
func (P *Printer) DoMapType(x *ast.MapType) { func (P *Printer) DoMapType(x *ast.MapType) {
P.Token(x.Pos(), token.MAP); P.Token(x.Pos(), token.MAP);
P.separator = blank; P.separator = blank;
P.Token(nopos, token.LBRACK); P.Token(noPos, token.LBRACK);
P.Expr(x.Key); P.Expr(x.Key);
P.Token(nopos, token.RBRACK); P.Token(noPos, token.RBRACK);
P.Expr(x.Value); P.Expr(x.Value);
} }
func (P *Printer) DoChannelType(x *ast.ChannelType) { func (P *Printer) DoChanType(x *ast.ChanType) {
switch x.Dir { switch x.Dir {
case ast.SEND | ast.RECV: case ast.SEND | ast.RECV:
P.Token(x.Pos(), token.CHAN); P.Token(x.Pos(), token.CHAN);
case ast.RECV: case ast.RECV:
P.Token(x.Pos(), token.ARROW); P.Token(x.Pos(), token.ARROW);
P.Token(nopos, token.CHAN); P.Token(noPos, token.CHAN);
case ast.SEND: case ast.SEND:
P.Token(x.Pos(), token.CHAN); P.Token(x.Pos(), token.CHAN);
P.separator = blank; P.separator = blank;
P.Token(nopos, token.ARROW); P.Token(noPos, token.ARROW);
} }
P.separator = blank; P.separator = blank;
P.Expr(x.Value); P.Expr(x.Value);
@ -835,7 +833,7 @@ func (P *Printer) DoEmptyStmt(s *ast.EmptyStmt) {
func (P *Printer) DoLabeledStmt(s *ast.LabeledStmt) { func (P *Printer) DoLabeledStmt(s *ast.LabeledStmt) {
P.indentation--; P.indentation--;
P.Expr(s.Label); P.Expr(s.Label);
P.Token(nopos, token.COLON); P.Token(noPos, token.COLON);
P.indentation++; P.indentation++;
// TODO be more clever if s.Stmt is a labeled stat as well // TODO be more clever if s.Stmt is a labeled stat as well
P.separator = tab; P.separator = tab;
@ -850,7 +848,7 @@ func (P *Printer) DoExprStmt(s *ast.ExprStmt) {
func (P *Printer) DoIncDecStmt(s *ast.IncDecStmt) { func (P *Printer) DoIncDecStmt(s *ast.IncDecStmt) {
P.Expr(s.X); P.Expr(s.X);
P.Token(nopos, s.Tok); P.Token(noPos, s.Tok);
} }
@ -931,7 +929,7 @@ func (P *Printer) Block(list []ast.Stmt, indent bool) {
P.Token(b.Rbrace, token.RBRACE); P.Token(b.Rbrace, token.RBRACE);
P.opt_semi = true; P.opt_semi = true;
} else { } else {
P.String(nopos, ""); // process closing_scope state transition! P.String(noPos, ""); // process closing_scope state transition!
} }
} }
*/ */
@ -964,14 +962,14 @@ func (P *Printer) ControlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
P.Stmt(init); P.Stmt(init);
P.separator = none; P.separator = none;
} }
P.Token(nopos, token.SEMICOLON); P.Token(noPos, token.SEMICOLON);
P.separator = blank; P.separator = blank;
if expr != nil { if expr != nil {
P.Expr(expr); P.Expr(expr);
P.separator = none; P.separator = none;
} }
if isForStmt { if isForStmt {
P.Token(nopos, token.SEMICOLON); P.Token(noPos, token.SEMICOLON);
P.separator = blank; P.separator = blank;
if post != nil { if post != nil {
P.Stmt(post); P.Stmt(post);
@ -988,7 +986,7 @@ func (P *Printer) DoIfStmt(s *ast.IfStmt) {
P.Stmt(s.Body); P.Stmt(s.Body);
if s.Else != nil { if s.Else != nil {
P.separator = blank; P.separator = blank;
P.Token(nopos, token.ELSE); P.Token(noPos, token.ELSE);
P.separator = blank; P.separator = blank;
P.Stmt(s.Else); P.Stmt(s.Else);
} }
@ -1040,7 +1038,7 @@ func (P *Printer) DoTypeSwitchStmt(s *ast.TypeSwitchStmt) {
if s.Init != nil { if s.Init != nil {
P.Stmt(s.Init); P.Stmt(s.Init);
P.separator = none; P.separator = none;
P.Token(nopos, token.SEMICOLON); P.Token(noPos, token.SEMICOLON);
} }
P.separator = blank; P.separator = blank;
P.Stmt(s.Assign); P.Stmt(s.Assign);
@ -1056,7 +1054,7 @@ func (P *Printer) DoCommClause(s *ast.CommClause) {
if s.Lhs != nil { if s.Lhs != nil {
P.Expr(s.Lhs); P.Expr(s.Lhs);
P.separator = blank; P.separator = blank;
P.Token(nopos, s.Tok); P.Token(noPos, s.Tok);
P.separator = blank; P.separator = blank;
} }
P.Expr(s.Rhs); P.Expr(s.Rhs);
@ -1090,7 +1088,7 @@ func (P *Printer) DoRangeStmt(s *ast.RangeStmt) {
P.separator = blank; P.separator = blank;
P.Expr(s.Key); P.Expr(s.Key);
if s.Value != nil { if s.Value != nil {
P.Token(nopos, token.COMMA); P.Token(noPos, token.COMMA);
P.separator = blank; P.separator = blank;
P.state = inside_list; P.state = inside_list;
P.Expr(s.Value); P.Expr(s.Value);
@ -1098,7 +1096,7 @@ func (P *Printer) DoRangeStmt(s *ast.RangeStmt) {
P.separator = blank; P.separator = blank;
P.Token(s.TokPos, s.Tok); P.Token(s.TokPos, s.Tok);
P.separator = blank; P.separator = blank;
P.Token(nopos, token.RANGE); P.Token(noPos, token.RANGE);
P.separator = blank; P.separator = blank;
P.Expr(s.X); P.Expr(s.X);
P.separator = blank; P.separator = blank;
@ -1146,7 +1144,7 @@ func (P *Printer) DoConstDecl(d *ast.ConstDecl) {
} }
if d.Values != nil { if d.Values != nil {
P.separator = tab; P.separator = tab;
P.Token(nopos, token.ASSIGN); P.Token(noPos, token.ASSIGN);
P.separator = blank; P.separator = blank;
P.Exprs(d.Values); P.Exprs(d.Values);
} }
@ -1179,7 +1177,7 @@ func (P *Printer) DoVarDecl(d *ast.VarDecl) {
} }
if d.Values != nil { if d.Values != nil {
P.separator = tab; P.separator = tab;
P.Token(nopos, token.ASSIGN); P.Token(noPos, token.ASSIGN);
P.separator = blank; P.separator = blank;
P.Exprs(d.Values); P.Exprs(d.Values);
} }
@ -1192,13 +1190,13 @@ func (P *Printer) DoFuncDecl(d *ast.FuncDecl) {
P.separator = blank; P.separator = blank;
if recv := d.Recv; recv != nil { if recv := d.Recv; recv != nil {
// method: print receiver // method: print receiver
P.Token(nopos, token.LPAREN); P.Token(noPos, token.LPAREN);
if len(recv.Names) > 0 { if len(recv.Names) > 0 {
P.Expr(recv.Names[0]); P.Expr(recv.Names[0]);
P.separator = blank; P.separator = blank;
} }
P.Expr(recv.Type); P.Expr(recv.Type);
P.Token(nopos, token.RPAREN); P.Token(noPos, token.RPAREN);
P.separator = blank; P.separator = blank;
} }
P.Expr(d.Name); P.Expr(d.Name);
@ -1217,7 +1215,7 @@ func (P *Printer) DoDeclList(d *ast.DeclList) {
// group of parenthesized declarations // group of parenthesized declarations
P.state = opening_scope; P.state = opening_scope;
P.Token(nopos, token.LPAREN); P.Token(noPos, token.LPAREN);
if len(d.List) > 0 { if len(d.List) > 0 {
P.newlines = 1; P.newlines = 1;
for i := 0; i < len(d.List); i++ { for i := 0; i < len(d.List); i++ {
@ -1240,123 +1238,10 @@ func (P *Printer) Decl(d ast.Decl) {
} }
// ----------------------------------------------------------------------------
// Package interface
func stripWhiteSpace(s []byte) []byte {
i, j := 0, len(s);
for i < len(s) && s[i] <= ' ' {
i++;
}
for j > i && s[j-1] <= ' ' {
j--
}
return s[i : j];
}
func cleanComment(s []byte) []byte {
switch s[1] {
case '/': s = s[2 : len(s)-1];
case '*': s = s[2 : len(s)-2];
default : panic("illegal comment");
}
return stripWhiteSpace(s);
}
func (P *Printer) printComment(comment ast.Comments) {
in_paragraph := false;
for i, c := range comment {
s := cleanComment(c.Text);
if len(s) > 0 {
if !in_paragraph {
P.Printf("<p>\n");
in_paragraph = true;
}
P.Printf("%s\n", P.htmlEscape(untabify(string(s))));
} else {
if in_paragraph {
P.Printf("</p>\n");
in_paragraph = false;
}
}
}
if in_paragraph {
P.Printf("</p>\n");
}
}
func (P *Printer) Interface(p *ast.Package) {
P.full = false;
for i := 0; i < len(p.Decls); i++ {
switch d := p.Decls[i].(type) {
case *ast.ConstDecl:
if hasExportedNames(d.Names) {
P.Printf("<h2>Constants</h2>\n");
P.Printf("<p><pre>");
P.DoConstDecl(d);
P.String(nopos, "");
P.Printf("</pre></p>\n");
if d.Doc != nil {
P.printComment(d.Doc);
}
}
case *ast.TypeDecl:
if isExported(d.Name) {
P.Printf("<h2>type %s</h2>\n", d.Name.Lit);
P.Printf("<p><pre>");
P.DoTypeDecl(d);
P.String(nopos, "");
P.Printf("</pre></p>\n");
if d.Doc != nil {
P.printComment(d.Doc);
}
}
case *ast.VarDecl:
if hasExportedNames(d.Names) {
P.Printf("<h2>Variables</h2>\n");
P.Printf("<p><pre>");
P.DoVarDecl(d);
P.String(nopos, "");
P.Printf("</pre></p>\n");
if d.Doc != nil {
P.printComment(d.Doc);
}
}
case *ast.FuncDecl:
if isExported(d.Name) {
if d.Recv != nil {
P.Printf("<h3>func (");
P.Expr(d.Recv.Type);
P.Printf(") %s</h3>\n", d.Name.Lit);
} else {
P.Printf("<h2>func %s</h2>\n", d.Name.Lit);
}
P.Printf("<p><code>");
P.DoFuncDecl(d);
P.String(nopos, "");
P.Printf("</code></p>\n");
if d.Doc != nil {
P.printComment(d.Doc);
}
}
case *ast.DeclList:
}
}
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Program // Program
func (P *Printer) Program(p *ast.Package) { func (P *Printer) DoProgram(p *ast.Program) {
P.full = true; P.full = true;
P.Token(p.Pos(), token.PACKAGE); P.Token(p.Pos(), token.PACKAGE);
P.separator = blank; P.separator = blank;

View File

@ -82,7 +82,7 @@ func (h *errorHandler) Error(pos token.Position, msg string) {
} }
func Compile(filename string, flags *Flags) (*ast.Package, ErrorList) { func Compile(filename string, flags *Flags) (*ast.Program, ErrorList) {
src, os_err := os.Open(filename, os.O_RDONLY, 0); src, os_err := os.Open(filename, os.O_RDONLY, 0);
defer src.Close(); defer src.Close();
if os_err != nil { if os_err != nil {

View File

@ -40,22 +40,22 @@ func hasExportedNames(names []*ast.Ident) bool {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
type constDoc struct { type constDoc struct {
cast *ast.ConstDecl; decl *ast.ConstDecl;
} }
type varDoc struct { type varDoc struct {
vast *ast.VarDecl; decl *ast.VarDecl;
} }
type funcDoc struct { type funcDoc struct {
fast *ast.FuncDecl; decl *ast.FuncDecl;
} }
type typeDoc struct { type typeDoc struct {
tast *ast.TypeDecl; decl *ast.TypeDecl;
methods map[string] *funcDoc; methods map[string] *funcDoc;
} }
@ -74,94 +74,284 @@ type PackageDoc struct {
// The package name is provided as initial argument. Use AddPackage to // The package name is provided as initial argument. Use AddPackage to
// add the AST for each source file belonging to the same package. // add the AST for each source file belonging to the same package.
// //
func (P *PackageDoc) Init(name string) { func (doc *PackageDoc) Init(name string) {
P.name = name; doc.name = name;
P.imports = make(map[string] string); doc.imports = make(map[string] string);
P.consts = make(map[string] *constDoc); doc.consts = make(map[string] *constDoc);
P.types = make(map[string] *typeDoc); doc.types = make(map[string] *typeDoc);
P.vars = make(map[string] *varDoc); doc.vars = make(map[string] *varDoc);
P.funcs = make(map[string] *funcDoc); doc.funcs = make(map[string] *funcDoc);
} }
func (P *PackageDoc) addDecl(decl ast.Decl) { func (doc *PackageDoc) addDecl(decl ast.Decl) {
switch d := decl.(type) { switch d := decl.(type) {
case *ast.ImportDecl: case *ast.ImportDecl:
case *ast.ConstDecl: case *ast.ConstDecl:
if hasExportedNames(d.Names) { if hasExportedNames(d.Names) {
} }
case *ast.TypeDecl: case *ast.TypeDecl:
if isExported(d.Name) { if isExported(d.Name) {
// TODO only add if not there already - or ignore?
name := string(d.Name.Lit);
tdoc := &typeDoc{d, make(map[string] *funcDoc)};
doc.types[name] = tdoc;
} }
case *ast.VarDecl: case *ast.VarDecl:
if hasExportedNames(d.Names) { if hasExportedNames(d.Names) {
} }
case *ast.FuncDecl: case *ast.FuncDecl:
if isExported(d.Name) { if isExported(d.Name) {
if d.Recv != nil { if d.Recv != nil {
// method // method
// determine receiver type name
var name string;
switch t := d.Recv.Type.(type) {
case *ast.Ident:
name = string(t.Lit);
case *ast.StarExpr:
// recv must be of the form *name
name = string(t.X.(*ast.Ident).Lit)
}
typ, found := doc.types[name];
if found {
fdoc := &funcDoc{d};
typ.methods[string(d.Name.Lit)] = fdoc;
}
// otherwise ignore
} else { } else {
// ordinary function // ordinary function
fdoc := &funcDoc{d};
doc.funcs[string(d.Name.Lit)] = fdoc;
} }
} }
case *ast.DeclList: case *ast.DeclList:
for i, decl := range d.List { for i, decl := range d.List {
P.addDecl(decl); doc.addDecl(decl);
} }
} }
} }
// AddPackage adds the AST of a source file belonging to the same // AddProgram adds the AST of a source file belonging to the same
// package. The package names must match. If the package was added // package. The package names must match. If the package was added
// before, AddPackage is a no-op. // before, AddPackage is a no-op.
// //
func (P *PackageDoc) AddPackage(pak *ast.Package) { func (doc *PackageDoc) AddProgram(pak *ast.Program) {
if P.name != string(pak.Name.Lit) { if doc.name != string(pak.Name.Lit) {
panic("package names don't match"); panic("package names don't match");
} }
// add all declarations // add all declarations
for i, decl := range pak.Decls { for i, decl := range pak.Decls {
P.addDecl(decl); doc.addDecl(decl);
} }
} }
func (P *PackageDoc) printConsts(p *astPrinter.Printer) { // ----------------------------------------------------------------------------
// Printing
func htmlEscape(s string) string {
var esc string;
for i := 0; i < len(s); i++ {
switch s[i] {
case '<': esc = "&lt;";
case '&': esc = "&amp;";
default: continue;
}
return s[0 : i] + esc + htmlEscape(s[i+1 : len(s)]);
}
return s;
} }
func (P *PackageDoc) printTypes(p *astPrinter.Printer) { // 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 *PackageDoc) printVars(p *astPrinter.Printer) { func stripWhiteSpace(s []byte) []byte {
i, j := 0, len(s);
for i < len(s) && s[i] <= ' ' {
i++;
}
for j > i && s[j-1] <= ' ' {
j--
}
return s[i : j];
} }
func (P *PackageDoc) printFuncs(p *astPrinter.Printer) { func cleanComment(s []byte) []byte {
switch s[1] {
case '/': s = s[2 : len(s)-1];
case '*': s = s[2 : len(s)-2];
default : panic("illegal comment");
}
return stripWhiteSpace(s);
} }
func (P *PackageDoc) printPackage(p *astPrinter.Printer) { func printComment(p *astPrinter.Printer, comment ast.Comments) {
in_paragraph := false;
for i, c := range comment {
s := cleanComment(c.Text);
if len(s) > 0 {
if !in_paragraph {
p.Printf("<p>\n");
in_paragraph = true;
}
p.Printf("%s\n", htmlEscape(untabify(string(s))));
} else {
if in_paragraph {
p.Printf("</p>\n");
in_paragraph = false;
}
}
}
if in_paragraph {
p.Printf("</p>\n");
}
} }
func (c *constDoc) printConsts(p *astPrinter.Printer) {
}
func (f *funcDoc) print(p *astPrinter.Printer) {
d := f.decl;
if d.Recv != nil {
p.Printf("<h3>func (");
p.Expr(d.Recv.Type);
p.Printf(") %s</h3>\n", d.Name.Lit);
} else {
p.Printf("<h2>func %s</h2>\n", d.Name.Lit);
}
p.Printf("<p><code>");
p.DoFuncDecl(d);
p.Printf("</code></p>\n");
if d.Doc != nil {
printComment(p, d.Doc);
}
}
func (t *typeDoc) print(p *astPrinter.Printer) {
d := t.decl;
p.Printf("<h2>type %s</h2>\n", string(d.Name.Lit));
p.Printf("<p><pre>");
p.DoTypeDecl(d);
p.Printf("</pre></p>\n");
if d.Doc != nil {
printComment(p, d.Doc);
}
// print associated methods, if any
for name, m := range t.methods {
m.print(p);
}
}
func (v *varDoc) print(p *astPrinter.Printer) {
}
/*
func (P *Printer) Interface(p *ast.Program) {
P.full = false;
for i := 0; i < len(p.Decls); i++ {
switch d := p.Decls[i].(type) {
case *ast.ConstDecl:
if hasExportedNames(d.Names) {
P.Printf("<h2>Constants</h2>\n");
P.Printf("<p><pre>");
P.DoConstDecl(d);
P.String(nopos, "");
P.Printf("</pre></p>\n");
if d.Doc != nil {
P.printComment(d.Doc);
}
}
case *ast.VarDecl:
if hasExportedNames(d.Names) {
P.Printf("<h2>Variables</h2>\n");
P.Printf("<p><pre>");
P.DoVarDecl(d);
P.String(nopos, "");
P.Printf("</pre></p>\n");
if d.Doc != nil {
P.printComment(d.Doc);
}
}
case *ast.DeclList:
}
}
}
*/
// TODO make this a parameter for Init or Print? // TODO make this a parameter for Init or Print?
var templ = template.NewTemplateOrDie("template.html"); var templ = template.NewTemplateOrDie("template.html");
func (P *PackageDoc) Print(writer io.Write) { func (doc *PackageDoc) Print(writer io.Write) {
var astp astPrinter.Printer; var p astPrinter.Printer;
astp.Init(writer, nil, true); p.Init(writer, nil, true);
err := templ.Apply(writer, "<!--", template.Substitution { // TODO propagate Apply errors
"PACKAGE_NAME-->" : func() { fmt.Fprint(writer, P.name); }, templ.Apply(writer, "<!--", template.Substitution {
"PACKAGE_COMMENT-->": func() { }, "PACKAGE_NAME-->" :
"PACKAGE_INTERFACE-->" : func() { }, func() {
"PACKAGE_BODY-->" : func() { }, fmt.Fprint(writer, doc.name);
}); },
if err != nil {
panic("print error - exiting"); "PROGRAM_HEADER-->":
func() {
},
"CONSTANTS-->" :
func() {
},
"TYPES-->" :
func() {
for name, t := range doc.types {
p.Printf("<hr />\n");
t.print(&p);
} }
},
"VARIABLES-->" :
func() {
},
"FUNCTIONS-->" :
func() {
for name, f := range doc.funcs {
p.Printf("<hr />\n");
f.print(&p);
}
},
});
} }

View File

@ -17,12 +17,11 @@ import (
"sort"; "sort";
"log"; "log";
"template"; "template";
"tabwriter";
"utils"; "utils";
"platform"; "platform";
"compilation"; "compilation";
"printer";
"tabwriter";
"docprinter"; "docprinter";
) )
@ -33,9 +32,8 @@ var (
root = flag.String("root", Platform.GOROOT, "go root directory"); root = flag.String("root", Platform.GOROOT, "go root directory");
// layout control // layout control
tabwidth = flag.Int("gds_tabwidth", 4, "tab width"); tabwidth = flag.Int("tabwidth", 4, "tab width");
usetabs = flag.Bool("gds_usetabs", false, "align with tabs instead of blanks"); usetabs = flag.Bool("usetabs", false, "align with tabs instead of blanks");
newdoc = flag.Bool("newdoc", false, "use new document printing"); // TODO remove once this works
) )
@ -167,7 +165,6 @@ func serveFile(c *http.Conn, filename string) {
c.SetHeader("content-type", "text/html; charset=utf-8"); c.SetHeader("content-type", "text/html; charset=utf-8");
if *newdoc {
// initialize tabwriter for nicely aligned output // initialize tabwriter for nicely aligned output
padchar := byte(' '); padchar := byte(' ');
if *usetabs { if *usetabs {
@ -178,7 +175,7 @@ func serveFile(c *http.Conn, filename string) {
// write documentation // write documentation
var doc docPrinter.PackageDoc; var doc docPrinter.PackageDoc;
doc.Init(string(prog.Name.Lit)); doc.Init(string(prog.Name.Lit));
doc.AddPackage(prog); doc.AddProgram(prog);
doc.Print(writer); doc.Print(writer);
// flush any pending output // flush any pending output
@ -186,11 +183,6 @@ func serveFile(c *http.Conn, filename string) {
if err != nil { if err != nil {
panic("print error - exiting"); panic("print error - exiting");
} }
} else {
// TODO remove once the new document stuff works better
// than the old code
Printer.Print(c, prog, true);
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -7,18 +7,25 @@ package main
import ( import (
"os"; "os";
"flag"; "flag";
Platform "platform"; "platform";
Printer "printer"; "compilation";
Compilation "compilation"; "tabwriter";
"ast";
"astprinter";
) )
var ( var (
flags Compilation.Flags; flags Compilation.Flags;
silent = flag.Bool("s", false, "silent mode: no pretty print output"); silent = flag.Bool("s", false, "silent mode: no pretty print output");
// layout control
html = flag.Bool("html", false, "generate html"); html = flag.Bool("html", false, "generate html");
tabwidth = flag.Int("pretty_tabwidth", 4, "tab width");
usetabs = flag.Bool("pretty_usetabs", false, "align with tabs instead of blanks");
) )
func init() { func init() {
flag.BoolVar(&flags.Verbose, "v", false, "verbose mode: trace parsing"); flag.BoolVar(&flags.Verbose, "v", false, "verbose mode: trace parsing");
flag.BoolVar(&flags.Deps, "d", false, "print dependency information only"); flag.BoolVar(&flags.Deps, "d", false, "print dependency information only");
@ -33,6 +40,25 @@ func usage() {
} }
func print(prog *ast.Program) {
// initialize tabwriter for nicely aligned output
padchar := byte(' ');
if *usetabs {
padchar = '\t';
}
writer := tabwriter.NewWriter(os.Stdout, *tabwidth, 1, padchar, tabwriter.FilterHTML);
// initialize printer
var printer astPrinter.Printer;
printer.Init(writer, prog.Comments, *html);
printer.DoProgram(prog);
// flush any pending output
writer.Flush();
}
func main() { func main() {
flag.Parse(); flag.Parse();
@ -53,7 +79,7 @@ func main() {
sys.Exit(1); sys.Exit(1);
} }
if !*silent { if !*silent {
Printer.Print(os.Stdout, prog, *html); print(prog);
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,16 @@
<font color=red>THIS SECTION IS CURRENTLY UNDER CONSTRUCTION</font> <font color=red>THIS SECTION IS CURRENTLY UNDER CONSTRUCTION</font>
<h1>package <!--PACKAGE_NAME--></h1> <h1>package <!--PACKAGE_NAME--></h1>
<!--PACKAGE_COMMENT-->
<!--PACKAGE_INTERFACE--> <!--PROGRAM_HEADER-->
<!--CONSTANTS-->
<!--TYPES-->
<!--VARIABLES-->
<!--FUNCTIONS-->
<hr /> <hr />
<h1>Implementation</h1> <h1>Implementation</h1>

View File

@ -77,7 +77,7 @@ func (s *state) CheckDeclaration(d *AST.Decl) {
*/ */
func (s *state) CheckProgram(p *ast.Package) { func (s *state) CheckProgram(p *ast.Program) {
for i := 0; i < len(p.Decls); i++ { for i := 0; i < len(p.Decls); i++ {
//s.CheckDeclaration(p.Decls[i].(*AST.Decl)); //s.CheckDeclaration(p.Decls[i].(*AST.Decl));
} }
@ -86,7 +86,7 @@ func (s *state) CheckProgram(p *ast.Package) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
func CheckProgram(err scanner.ErrorHandler, p *ast.Package) { func CheckProgram(err scanner.ErrorHandler, p *ast.Program) {
var s state; var s state;
s.Init(err); s.Init(err);
s.CheckProgram(p); s.CheckProgram(p);