mirror of
https://github.com/golang/go.git
synced 2025-05-15 12:24:37 +00:00
daily snapshot:
- correctly associate comments with declarations (available through AST) - very raw printing of interface - much more functionality, now needs some formatting, sorting, etc. R=r OCL=26213 CL=26213
This commit is contained in:
parent
ce9417ee1a
commit
e06a654ce1
@ -28,6 +28,21 @@ func assert(pred bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Comments
|
||||||
|
|
||||||
|
type Comment struct {
|
||||||
|
Loc scanner.Location;
|
||||||
|
EndLine int; // the line where the comment ends
|
||||||
|
Text []byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A CommentGroup is a sequence of consequtive comments
|
||||||
|
// with no other tokens and no empty lines inbetween.
|
||||||
|
type CommentGroup []*Comment
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Expressions
|
// Expressions
|
||||||
|
|
||||||
@ -132,6 +147,7 @@ type (
|
|||||||
Idents []*Ident;
|
Idents []*Ident;
|
||||||
Typ Expr;
|
Typ Expr;
|
||||||
Tag Expr; // nil = no tag
|
Tag Expr; // nil = no tag
|
||||||
|
Comment CommentGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
StructType struct {
|
StructType struct {
|
||||||
@ -445,12 +461,14 @@ type (
|
|||||||
Idents []*Ident;
|
Idents []*Ident;
|
||||||
Typ Expr;
|
Typ Expr;
|
||||||
Vals Expr;
|
Vals Expr;
|
||||||
|
Comment CommentGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
TypeDecl struct {
|
TypeDecl struct {
|
||||||
Loc scanner.Location; // if > 0: position of "type"
|
Loc scanner.Location; // if > 0: position of "type"
|
||||||
Ident *Ident;
|
Ident *Ident;
|
||||||
Typ Expr;
|
Typ Expr;
|
||||||
|
Comment CommentGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
VarDecl struct {
|
VarDecl struct {
|
||||||
@ -458,6 +476,7 @@ type (
|
|||||||
Idents []*Ident;
|
Idents []*Ident;
|
||||||
Typ Expr;
|
Typ Expr;
|
||||||
Vals Expr;
|
Vals Expr;
|
||||||
|
Comment CommentGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
FuncDecl struct {
|
FuncDecl struct {
|
||||||
@ -466,6 +485,7 @@ type (
|
|||||||
Ident *Ident;
|
Ident *Ident;
|
||||||
Sig *Signature;
|
Sig *Signature;
|
||||||
Body *Block;
|
Body *Block;
|
||||||
|
Comment CommentGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
DeclList struct {
|
DeclList struct {
|
||||||
@ -500,17 +520,13 @@ func (d *DeclList) Visit(v DeclVisitor) { v.DoDeclList(d); }
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Program
|
// Program
|
||||||
|
|
||||||
type Comment struct {
|
// TODO rename to Package
|
||||||
Loc scanner.Location;
|
|
||||||
Text []byte;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
type Program struct {
|
type Program struct {
|
||||||
Loc scanner.Location; // tok is token.PACKAGE
|
Loc scanner.Location; // tok is token.PACKAGE
|
||||||
Ident *Ident;
|
Ident *Ident;
|
||||||
Decls []Decl;
|
Decls []Decl;
|
||||||
Comments []*Comment;
|
Comment CommentGroup;
|
||||||
|
Comments []CommentGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ func Compile(src_file string, flags *Flags) (*AST.Program, int) {
|
|||||||
var parser Parser.Parser;
|
var parser Parser.Parser;
|
||||||
parser.Init(&scanner, &err, flags.Verbose);
|
parser.Init(&scanner, &err, flags.Verbose);
|
||||||
|
|
||||||
prog := parser.ParseProgram();
|
prog := parser.Parse(Parser.ParseEntirePackage);
|
||||||
|
|
||||||
if err.nerrors == 0 {
|
if err.nerrors == 0 {
|
||||||
TypeChecker.CheckProgram(&err, prog);
|
TypeChecker.CheckProgram(&err, prog);
|
||||||
|
@ -108,7 +108,7 @@ 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");
|
||||||
Printer.Print(c, true, prog);
|
Printer.Print(c, prog, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,7 +33,8 @@ type Parser struct {
|
|||||||
trace bool;
|
trace bool;
|
||||||
indent uint;
|
indent uint;
|
||||||
|
|
||||||
comments *vector.Vector;
|
comments vector.Vector;
|
||||||
|
last_comment ast.CommentGroup;
|
||||||
|
|
||||||
// The next token
|
// The next token
|
||||||
loc scanner.Location; // token location
|
loc scanner.Location; // token location
|
||||||
@ -42,8 +43,6 @@ type Parser struct {
|
|||||||
|
|
||||||
// Non-syntactic parser control
|
// Non-syntactic parser control
|
||||||
opt_semi bool; // true if semicolon separator is optional in statement list
|
opt_semi bool; // true if semicolon separator is optional in statement list
|
||||||
|
|
||||||
// Nesting levels
|
|
||||||
expr_lev int; // < 0: in control clause, >= 0: in expression
|
expr_lev int; // < 0: in control clause, >= 0: in expression
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,9 +112,63 @@ func (P *Parser) next0() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (P *Parser) getComment() *ast.Comment {
|
||||||
|
defer P.next0();
|
||||||
|
|
||||||
|
// for /*-style comments, the comment may end on a different line
|
||||||
|
endline := P.loc.Line;
|
||||||
|
if P.val[1] == '*' {
|
||||||
|
for i, b := range P.val {
|
||||||
|
if b == '\n' {
|
||||||
|
endline++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ast.Comment{P.loc, endline, P.val};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (P *Parser) getCommentGroup() ast.CommentGroup {
|
||||||
|
list := vector.New(0);
|
||||||
|
|
||||||
|
// group adjacent comments
|
||||||
|
// (an empty line terminates a group)
|
||||||
|
endline := P.loc.Line;
|
||||||
|
for P.tok == token.COMMENT && endline+1 >= P.loc.Line {
|
||||||
|
c := P.getComment();
|
||||||
|
list.Push(c);
|
||||||
|
endline = c.EndLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert list
|
||||||
|
group := make(ast.CommentGroup, list.Len());
|
||||||
|
for i := 0; i < list.Len(); i++ {
|
||||||
|
group[i] = list.At(i).(*ast.Comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (P *Parser) getLastComment() ast.CommentGroup {
|
||||||
|
c := P.last_comment;
|
||||||
|
if c != nil && c[len(c) - 1].EndLine + 1 < P.loc.Line {
|
||||||
|
// empty line between last comment and current token,
|
||||||
|
// at least one line of space between last comment
|
||||||
|
// and current token; ignore this comment
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) next() {
|
func (P *Parser) next() {
|
||||||
for P.next0(); P.tok == token.COMMENT; P.next0() {
|
P.next0();
|
||||||
P.comments.Push(&ast.Comment{P.loc, P.val});
|
P.last_comment = nil;
|
||||||
|
for P.tok == token.COMMENT {
|
||||||
|
P.last_comment = P.getCommentGroup();
|
||||||
|
P.comments.Push(P.last_comment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,14 +176,9 @@ func (P *Parser) next() {
|
|||||||
func (P *Parser) Init(scanner *scanner.Scanner, err scanner.ErrorHandler, trace bool) {
|
func (P *Parser) Init(scanner *scanner.Scanner, err scanner.ErrorHandler, trace bool) {
|
||||||
P.scanner = scanner;
|
P.scanner = scanner;
|
||||||
P.err = err;
|
P.err = err;
|
||||||
|
|
||||||
P.trace = trace;
|
P.trace = trace;
|
||||||
P.indent = 0;
|
P.comments.Init(0);
|
||||||
|
|
||||||
P.comments = vector.New(0);
|
|
||||||
|
|
||||||
P.next();
|
P.next();
|
||||||
P.expr_lev = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -382,20 +430,20 @@ func (P *Parser) parseParameterList(ellipsis_ok bool) []*ast.Field {
|
|||||||
idents[i] = list.At(i).(*ast.Ident);
|
idents[i] = list.At(i).(*ast.Ident);
|
||||||
}
|
}
|
||||||
list.Init(0);
|
list.Init(0);
|
||||||
list.Push(&ast.Field{idents, typ, nil});
|
list.Push(&ast.Field{idents, typ, nil, nil});
|
||||||
|
|
||||||
for P.tok == token.COMMA {
|
for P.tok == token.COMMA {
|
||||||
P.next();
|
P.next();
|
||||||
idents := P.parseIdentList2(nil);
|
idents := P.parseIdentList2(nil);
|
||||||
typ := P.parseParameterType();
|
typ := P.parseParameterType();
|
||||||
list.Push(&ast.Field{idents, typ, nil});
|
list.Push(&ast.Field{idents, typ, nil, nil});
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Type { "," Type }
|
// Type { "," Type }
|
||||||
// convert list of types into list of *Param
|
// convert list of types into list of *Param
|
||||||
for i := 0; i < list.Len(); i++ {
|
for i := 0; i < list.Len(); i++ {
|
||||||
list.Set(i, &ast.Field{nil, list.At(i).(ast.Expr), nil});
|
list.Set(i, &ast.Field{nil, list.At(i).(ast.Expr), nil, nil});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +486,7 @@ func (P *Parser) parseResult() []*ast.Field {
|
|||||||
typ := P.tryType();
|
typ := P.tryType();
|
||||||
if typ != nil {
|
if typ != nil {
|
||||||
result = make([]*ast.Field, 1);
|
result = make([]*ast.Field, 1);
|
||||||
result[0] = &ast.Field{nil, typ, nil};
|
result[0] = &ast.Field{nil, typ, nil, nil};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,7 +543,7 @@ func (P *Parser) parseMethodSpec() *ast.Field {
|
|||||||
typ = x;
|
typ = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ast.Field{idents, typ, nil};
|
return &ast.Field{idents, typ, nil, nil};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -558,6 +606,8 @@ func (P *Parser) parseFieldDecl() *ast.Field {
|
|||||||
defer un(trace(P, "FieldDecl"));
|
defer un(trace(P, "FieldDecl"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comment := P.getLastComment();
|
||||||
|
|
||||||
// a list of identifiers looks like a list of type names
|
// a list of identifiers looks like a list of type names
|
||||||
list := vector.New(0);
|
list := vector.New(0);
|
||||||
for {
|
for {
|
||||||
@ -601,7 +651,7 @@ func (P *Parser) parseFieldDecl() *ast.Field {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ast.Field{idents, typ, tag};
|
return &ast.Field{idents, typ, tag, comment};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1377,24 +1427,25 @@ func (P *Parser) parseImportSpec(loc scanner.Location) *ast.ImportDecl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) parseConstSpec(loc scanner.Location) *ast.ConstDecl {
|
func (P *Parser) parseConstSpec(loc scanner.Location, comment ast.CommentGroup) *ast.ConstDecl {
|
||||||
if P.trace {
|
if P.trace {
|
||||||
defer un(trace(P, "ConstSpec"));
|
defer un(trace(P, "ConstSpec"));
|
||||||
}
|
}
|
||||||
|
|
||||||
idents := P.parseIdentList2(nil);
|
idents := P.parseIdentList2(nil);
|
||||||
typ := P.tryType();
|
typ := P.tryType();
|
||||||
|
|
||||||
var vals ast.Expr;
|
var vals ast.Expr;
|
||||||
if P.tok == token.ASSIGN {
|
if P.tok == token.ASSIGN {
|
||||||
P.next();
|
P.next();
|
||||||
vals = P.parseExpressionList();
|
vals = P.parseExpressionList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ast.ConstDecl{loc, idents, typ, vals};
|
return &ast.ConstDecl{loc, idents, typ, vals, comment};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) parseTypeSpec(loc scanner.Location) *ast.TypeDecl {
|
func (P *Parser) parseTypeSpec(loc scanner.Location, comment ast.CommentGroup) *ast.TypeDecl {
|
||||||
if P.trace {
|
if P.trace {
|
||||||
defer un(trace(P, "TypeSpec"));
|
defer un(trace(P, "TypeSpec"));
|
||||||
}
|
}
|
||||||
@ -1402,11 +1453,11 @@ func (P *Parser) parseTypeSpec(loc scanner.Location) *ast.TypeDecl {
|
|||||||
ident := P.parseIdent();
|
ident := P.parseIdent();
|
||||||
typ := P.parseType();
|
typ := P.parseType();
|
||||||
|
|
||||||
return &ast.TypeDecl{loc, ident, typ};
|
return &ast.TypeDecl{loc, ident, typ, comment};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) parseVarSpec(loc scanner.Location) *ast.VarDecl {
|
func (P *Parser) parseVarSpec(loc scanner.Location, comment ast.CommentGroup) *ast.VarDecl {
|
||||||
if P.trace {
|
if P.trace {
|
||||||
defer un(trace(P, "VarSpec"));
|
defer un(trace(P, "VarSpec"));
|
||||||
}
|
}
|
||||||
@ -1425,16 +1476,16 @@ func (P *Parser) parseVarSpec(loc scanner.Location) *ast.VarDecl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ast.VarDecl{loc, idents, typ, vals};
|
return &ast.VarDecl{loc, idents, typ, vals, comment};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) parseSpec(loc scanner.Location, keyword int) ast.Decl {
|
func (P *Parser) parseSpec(loc scanner.Location, comment ast.CommentGroup, keyword int) ast.Decl {
|
||||||
switch keyword {
|
switch keyword {
|
||||||
case token.IMPORT: return P.parseImportSpec(loc);
|
case token.IMPORT: return P.parseImportSpec(loc);
|
||||||
case token.CONST: return P.parseConstSpec(loc);
|
case token.CONST: return P.parseConstSpec(loc, comment);
|
||||||
case token.TYPE: return P.parseTypeSpec(loc);
|
case token.TYPE: return P.parseTypeSpec(loc, comment);
|
||||||
case token.VAR: return P.parseVarSpec(loc);
|
case token.VAR: return P.parseVarSpec(loc, comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
unreachable();
|
unreachable();
|
||||||
@ -1447,13 +1498,14 @@ func (P *Parser) parseDecl(keyword int) ast.Decl {
|
|||||||
defer un(trace(P, "Decl"));
|
defer un(trace(P, "Decl"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comment := P.getLastComment();
|
||||||
loc := P.loc;
|
loc := P.loc;
|
||||||
P.expect(keyword);
|
P.expect(keyword);
|
||||||
if P.tok == token.LPAREN {
|
if P.tok == token.LPAREN {
|
||||||
P.next();
|
P.next();
|
||||||
list := vector.New(0);
|
list := vector.New(0);
|
||||||
for P.tok != token.RPAREN && P.tok != token.EOF {
|
for P.tok != token.RPAREN && P.tok != token.EOF {
|
||||||
list.Push(P.parseSpec(noloc, keyword));
|
list.Push(P.parseSpec(noloc, nil, keyword));
|
||||||
if P.tok == token.SEMICOLON {
|
if P.tok == token.SEMICOLON {
|
||||||
P.next();
|
P.next();
|
||||||
} else {
|
} else {
|
||||||
@ -1473,7 +1525,7 @@ func (P *Parser) parseDecl(keyword int) ast.Decl {
|
|||||||
return &ast.DeclList{loc, keyword, decls, end};
|
return &ast.DeclList{loc, keyword, decls, end};
|
||||||
}
|
}
|
||||||
|
|
||||||
return P.parseSpec(loc, keyword);
|
return P.parseSpec(loc, comment, keyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1491,6 +1543,7 @@ func (P *Parser) parseFunctionDecl() *ast.FuncDecl {
|
|||||||
defer un(trace(P, "FunctionDecl"));
|
defer un(trace(P, "FunctionDecl"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comment := P.getLastComment();
|
||||||
loc := P.loc;
|
loc := P.loc;
|
||||||
P.expect(token.FUNC);
|
P.expect(token.FUNC);
|
||||||
|
|
||||||
@ -1513,7 +1566,7 @@ func (P *Parser) parseFunctionDecl() *ast.FuncDecl {
|
|||||||
body = P.parseBlock(token.LBRACE);
|
body = P.parseBlock(token.LBRACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ast.FuncDecl{loc, recv, ident, sig, body};
|
return &ast.FuncDecl{loc, recv, ident, sig, body, comment};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1539,98 +1592,68 @@ func (P *Parser) parseDeclaration() ast.Decl {
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Program
|
// Program
|
||||||
|
|
||||||
// The top level parsing routines:
|
func (P *Parser) getComments() []ast.CommentGroup {
|
||||||
//
|
|
||||||
// ParsePackageClause
|
|
||||||
// - parses the package clause only and returns the package name
|
|
||||||
//
|
|
||||||
// ParseImportDecls
|
|
||||||
// - parses all import declarations and returns a list of them
|
|
||||||
// - the package clause must have been parsed before
|
|
||||||
// - useful to determine package dependencies
|
|
||||||
//
|
|
||||||
// ParseProgram
|
|
||||||
// - parses the entire program and returns the complete AST
|
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) ParsePackageClause() *ast.Ident {
|
|
||||||
if P.trace {
|
|
||||||
defer un(trace(P, "PackageClause"));
|
|
||||||
}
|
|
||||||
|
|
||||||
P.expect(token.PACKAGE);
|
|
||||||
return P.parseIdent();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) parseImportDecls() *vector.Vector {
|
|
||||||
if P.trace {
|
|
||||||
defer un(trace(P, "ImportDecls"));
|
|
||||||
}
|
|
||||||
|
|
||||||
list := vector.New(0);
|
|
||||||
for P.tok == token.IMPORT {
|
|
||||||
list.Push(P.parseDecl(token.IMPORT));
|
|
||||||
if P.tok == token.SEMICOLON {
|
|
||||||
P.next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) ParseImportDecls() []ast.Decl {
|
|
||||||
list := P.parseImportDecls();
|
|
||||||
|
|
||||||
// convert list
|
|
||||||
imports := make([]ast.Decl, list.Len());
|
|
||||||
for i := 0; i < list.Len(); i++ {
|
|
||||||
imports[i] = list.At(i).(ast.Decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
return imports;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Returns the list of comments accumulated during parsing, if any.
|
|
||||||
// (The scanner must return token.COMMENT tokens for comments to be
|
|
||||||
// collected in the first place.)
|
|
||||||
|
|
||||||
func (P *Parser) Comments() []*ast.Comment {
|
|
||||||
// convert comments vector
|
// convert comments vector
|
||||||
list := make([]*ast.Comment, P.comments.Len());
|
list := make([]ast.CommentGroup, P.comments.Len());
|
||||||
for i := 0; i < P.comments.Len(); i++ {
|
for i := 0; i < P.comments.Len(); i++ {
|
||||||
list[i] = P.comments.At(i).(*ast.Comment);
|
list[i] = P.comments.At(i).(ast.CommentGroup);
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) ParseProgram() *ast.Program {
|
// The Parse function is parametrized with one of the following
|
||||||
|
// constants. They control how much of the source text is parsed.
|
||||||
|
//
|
||||||
|
const (
|
||||||
|
ParseEntirePackage = iota;
|
||||||
|
ParseImportDeclsOnly;
|
||||||
|
ParsePackageClauseOnly;
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// Parse parses the source...
|
||||||
|
//
|
||||||
|
// foo bar
|
||||||
|
//
|
||||||
|
func (P *Parser) Parse(mode int) *ast.Program {
|
||||||
if P.trace {
|
if P.trace {
|
||||||
defer un(trace(P, "Program"));
|
defer un(trace(P, "Program"));
|
||||||
}
|
}
|
||||||
|
|
||||||
p := ast.NewProgram(P.loc);
|
// package clause
|
||||||
p.Ident = P.ParsePackageClause();
|
comment := P.getLastComment();
|
||||||
|
loc := P.loc;
|
||||||
|
P.expect(token.PACKAGE);
|
||||||
|
name := P.parseIdent();
|
||||||
|
var decls []ast.Decl;
|
||||||
|
|
||||||
// package body
|
if mode <= ParseImportDeclsOnly {
|
||||||
list := P.parseImportDecls();
|
// import decls
|
||||||
for P.tok != token.EOF {
|
list := vector.New(0);
|
||||||
list.Push(P.parseDeclaration());
|
for P.tok == token.IMPORT {
|
||||||
if P.tok == token.SEMICOLON {
|
list.Push(P.parseDecl(token.IMPORT));
|
||||||
P.next();
|
if P.tok == token.SEMICOLON {
|
||||||
|
P.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if mode <= ParseEntirePackage {
|
||||||
|
// rest of package body
|
||||||
|
for P.tok != token.EOF {
|
||||||
|
list.Push(P.parseDeclaration());
|
||||||
|
if P.tok == token.SEMICOLON {
|
||||||
|
P.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert list
|
||||||
|
decls = make([]ast.Decl, list.Len());
|
||||||
|
for i := 0; i < list.Len(); i++ {
|
||||||
|
decls[i] = list.At(i).(ast.Decl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert list
|
return &ast.Program{loc, name, decls, comment, P.getComments()};
|
||||||
p.Decls = make([]ast.Decl, list.Len());
|
|
||||||
for i := 0; i < list.Len(); i++ {
|
|
||||||
p.Decls[i] = list.At(i).(ast.Decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Comments = P.Comments();
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func main() {
|
|||||||
sys.Exit(1);
|
sys.Exit(1);
|
||||||
}
|
}
|
||||||
if !*silent {
|
if !*silent {
|
||||||
Printer.Print(os.Stdout, *html, prog);
|
Printer.Print(os.Stdout, prog, *html);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,11 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
debug = flag.Bool("debug", false, "print debugging information");
|
debug = flag.Bool("debug", false, "print debugging information");
|
||||||
def = flag.Bool("def", false, "print 'def' instead of 'const', 'type', 'func' - experimental");
|
|
||||||
|
|
||||||
// layout control
|
// layout control
|
||||||
tabwidth = flag.Int("tabwidth", 8, "tab width");
|
tabwidth = flag.Int("tabwidth", 8, "tab width");
|
||||||
usetabs = flag.Bool("usetabs", true, "align with tabs instead of blanks");
|
usetabs = flag.Bool("usetabs", true, "align with tabs instead of blanks");
|
||||||
newlines = flag.Bool("newlines", true, "respect newlines in source");
|
newlines = flag.Bool("newlines", false, "respect newlines in source");
|
||||||
maxnewlines = flag.Int("maxnewlines", 3, "max. number of consecutive newlines");
|
maxnewlines = flag.Int("maxnewlines", 3, "max. number of consecutive newlines");
|
||||||
|
|
||||||
// formatting control
|
// formatting control
|
||||||
@ -63,6 +62,23 @@ func assert(pred bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO this should be an AST method
|
||||||
|
func isExported(name *ast.Ident) bool {
|
||||||
|
ch, len := utf8.DecodeRuneInString(name.Str, 0);
|
||||||
|
return unicode.IsUpper(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func hasExportedNames(names []*ast.Ident) bool {
|
||||||
|
for i, name := range names {
|
||||||
|
if isExported(name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Printer
|
// Printer
|
||||||
|
|
||||||
@ -91,14 +107,15 @@ type Printer struct {
|
|||||||
|
|
||||||
// formatting control
|
// formatting control
|
||||||
html bool;
|
html bool;
|
||||||
|
full bool; // if false, print interface only; print all otherwise
|
||||||
|
|
||||||
// comments
|
// comments
|
||||||
comments []*ast.Comment; // the list of all comments
|
comments []ast.CommentGroup; // the list of all comments groups
|
||||||
cindex int; // the current comments index
|
cindex int; // the current comment group index
|
||||||
cpos int; // the position of the next comment
|
cloc scanner.Location; // the position of the next comment group
|
||||||
|
|
||||||
// current state
|
// current state
|
||||||
lastpos int; // pos after last string
|
lastloc scanner.Location; // location after last string
|
||||||
level int; // scope level
|
level int; // scope level
|
||||||
indentation int; // indentation level (may be different from scope level)
|
indentation int; // indentation level (may be different from scope level)
|
||||||
|
|
||||||
@ -116,22 +133,22 @@ type Printer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) HasComment(pos int) bool {
|
func (P *Printer) hasComment(loc scanner.Location) bool {
|
||||||
return *comments && P.cpos < pos;
|
return *comments && P.cloc.Pos < loc.Pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) NextComment() {
|
func (P *Printer) nextCommentGroup() {
|
||||||
P.cindex++;
|
P.cindex++;
|
||||||
if P.comments != nil && P.cindex < len(P.comments) {
|
if P.comments != nil && P.cindex < len(P.comments) {
|
||||||
P.cpos = P.comments[P.cindex].Loc.Pos;
|
P.cloc = P.comments[P.cindex][0].Loc;
|
||||||
} else {
|
} else {
|
||||||
P.cpos = 1<<30; // infinite
|
P.cloc = scanner.Location{1<<30, 1<<30, 1}; // infinite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) Init(text io.Write, html bool, comments []*ast.Comment) {
|
func (P *Printer) Init(text io.Write, comments []ast.CommentGroup, html bool) {
|
||||||
// writers
|
// writers
|
||||||
P.text = text;
|
P.text = text;
|
||||||
|
|
||||||
@ -141,7 +158,7 @@ func (P *Printer) Init(text io.Write, html bool, comments []*ast.Comment) {
|
|||||||
// comments
|
// comments
|
||||||
P.comments = comments;
|
P.comments = comments;
|
||||||
P.cindex = -1;
|
P.cindex = -1;
|
||||||
P.NextComment();
|
P.nextCommentGroup();
|
||||||
|
|
||||||
// formatting parameters & semantic state initialized correctly by default
|
// formatting parameters & semantic state initialized correctly by default
|
||||||
|
|
||||||
@ -194,14 +211,15 @@ func (P *Printer) Printf(format string, s ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) Newline(n int) {
|
func (P *Printer) newline(n int) {
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
m := int(*maxnewlines);
|
m := int(*maxnewlines);
|
||||||
if n > m {
|
if n > m {
|
||||||
n = m;
|
n = m;
|
||||||
}
|
}
|
||||||
for ; n > 0; n-- {
|
for n > 0 {
|
||||||
P.Printf("\n");
|
P.Printf("\n");
|
||||||
|
n--;
|
||||||
}
|
}
|
||||||
for i := P.indentation; i > 0; i-- {
|
for i := P.indentation; i > 0; i-- {
|
||||||
P.Printf("\t");
|
P.Printf("\t");
|
||||||
@ -214,7 +232,7 @@ func (P *Printer) TaggedString(loc scanner.Location, tag, s, endtag string) {
|
|||||||
// use estimate for pos if we don't have one
|
// use estimate for pos if we don't have one
|
||||||
pos := loc.Pos;
|
pos := loc.Pos;
|
||||||
if pos == 0 {
|
if pos == 0 {
|
||||||
pos = P.lastpos;
|
pos = P.lastloc.Pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
@ -252,26 +270,22 @@ func (P *Printer) TaggedString(loc scanner.Location, tag, s, endtag string) {
|
|||||||
// --------------------------------
|
// --------------------------------
|
||||||
// interleave comments, if any
|
// interleave comments, if any
|
||||||
nlcount := 0;
|
nlcount := 0;
|
||||||
for ; P.HasComment(pos); P.NextComment() {
|
if P.full {
|
||||||
// we have a comment/newline that comes before the string
|
for ; P.hasComment(loc); P.nextCommentGroup() {
|
||||||
comment := P.comments[P.cindex];
|
// we have a comment group that comes before the string
|
||||||
ctext := string(comment.Text); // TODO get rid of string conversion here
|
comment := P.comments[P.cindex][0]; // TODO broken
|
||||||
|
ctext := string(comment.Text); // TODO get rid of string conversion here
|
||||||
|
|
||||||
if ctext == "\n" {
|
|
||||||
// found a newline in src - count it
|
|
||||||
nlcount++;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// classify comment (len(ctext) >= 2)
|
// classify comment (len(ctext) >= 2)
|
||||||
//-style comment
|
//-style comment
|
||||||
if nlcount > 0 || P.cpos == 0 {
|
if nlcount > 0 || P.cloc.Pos == 0 {
|
||||||
// only white space before comment on this line
|
// only white space before comment on this line
|
||||||
// or file starts with comment
|
// or file starts with comment
|
||||||
// - indent
|
// - indent
|
||||||
if !*newlines && P.cpos != 0 {
|
if !*newlines && P.cloc.Pos != 0 {
|
||||||
nlcount = 1;
|
nlcount = 1;
|
||||||
}
|
}
|
||||||
P.Newline(nlcount);
|
P.newline(nlcount);
|
||||||
nlcount = 0;
|
nlcount = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -304,23 +318,16 @@ func (P *Printer) TaggedString(loc scanner.Location, tag, s, endtag string) {
|
|||||||
|
|
||||||
// print comment
|
// print comment
|
||||||
if *debug {
|
if *debug {
|
||||||
P.Printf("[%d]", P.cpos);
|
P.Printf("[%d]", P.cloc.Pos);
|
||||||
}
|
}
|
||||||
// calling untabify increases the change for idempotent output
|
// calling untabify increases the change for idempotent output
|
||||||
// since tabs in comments are also interpreted by tabwriter
|
// since tabs in comments are also interpreted by tabwriter
|
||||||
P.Printf("%s", P.htmlEscape(untabify(ctext)));
|
P.Printf("%s", P.htmlEscape(untabify(ctext)));
|
||||||
|
|
||||||
if ctext[1] == '/' {
|
|
||||||
//-style comments must end in newline
|
|
||||||
if P.newlines == 0 { // don't add newlines if not needed
|
|
||||||
P.newlines = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// 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.
|
||||||
}
|
}
|
||||||
// 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
|
// interpret state
|
||||||
@ -346,7 +353,7 @@ func (P *Printer) TaggedString(loc scanner.Location, tag, s, endtag string) {
|
|||||||
P.newlines = nlcount;
|
P.newlines = nlcount;
|
||||||
}
|
}
|
||||||
nlcount = 0;
|
nlcount = 0;
|
||||||
P.Newline(P.newlines);
|
P.newline(P.newlines);
|
||||||
P.newlines = 0;
|
P.newlines = 0;
|
||||||
|
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
@ -375,7 +382,9 @@ func (P *Printer) TaggedString(loc scanner.Location, tag, s, endtag string) {
|
|||||||
// --------------------------------
|
// --------------------------------
|
||||||
// done
|
// done
|
||||||
P.opt_semi = false;
|
P.opt_semi = false;
|
||||||
P.lastpos = pos + len(s); // rough estimate
|
loc.Pos += len(s); // rough estimate
|
||||||
|
loc.Col += len(s); // rough estimate
|
||||||
|
P.lastloc = loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -437,15 +446,20 @@ func (P *Printer) HtmlPackageName(loc scanner.Location, name string) {
|
|||||||
|
|
||||||
func (P *Printer) Expr(x ast.Expr)
|
func (P *Printer) Expr(x ast.Expr)
|
||||||
|
|
||||||
func (P *Printer) Idents(list []*ast.Ident) {
|
func (P *Printer) Idents(list []*ast.Ident, full bool) int {
|
||||||
|
n := 0;
|
||||||
for i, x := range list {
|
for i, x := range list {
|
||||||
if i > 0 {
|
if n > 0 {
|
||||||
P.Token(noloc, token.COMMA);
|
P.Token(noloc, token.COMMA);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.state = inside_list;
|
P.state = inside_list;
|
||||||
}
|
}
|
||||||
P.Expr(x);
|
if full || isExported(x) {
|
||||||
|
P.Expr(x);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -456,8 +470,8 @@ func (P *Printer) Parameters(list []*ast.Field) {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
P.separator = comma;
|
P.separator = comma;
|
||||||
}
|
}
|
||||||
if len(par.Idents) > 0 {
|
n := P.Idents(par.Idents, true);
|
||||||
P.Idents(par.Idents);
|
if n > 0 {
|
||||||
P.separator = blank
|
P.separator = blank
|
||||||
};
|
};
|
||||||
P.Expr(par.Typ);
|
P.Expr(par.Typ);
|
||||||
@ -501,21 +515,25 @@ func (P *Printer) Fields(list []*ast.Field, end scanner.Location, is_interface b
|
|||||||
P.separator = semicolon;
|
P.separator = semicolon;
|
||||||
P.newlines = 1;
|
P.newlines = 1;
|
||||||
}
|
}
|
||||||
if len(fld.Idents) > 0 {
|
n := P.Idents(fld.Idents, P.full);
|
||||||
P.Idents(fld.Idents);
|
if n > 0 {
|
||||||
|
// at least one identifier
|
||||||
P.separator = tab
|
P.separator = tab
|
||||||
};
|
};
|
||||||
if is_interface {
|
if n > 0 || len(fld.Idents) == 0 {
|
||||||
if ftyp, is_ftyp := fld.Typ.(*ast.FunctionType); is_ftyp {
|
// at least one identifier or anonymous field
|
||||||
P.Signature(ftyp.Sig);
|
if is_interface {
|
||||||
|
if ftyp, is_ftyp := fld.Typ.(*ast.FunctionType); is_ftyp {
|
||||||
|
P.Signature(ftyp.Sig);
|
||||||
|
} else {
|
||||||
|
P.Expr(fld.Typ);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
P.Expr(fld.Typ);
|
P.Expr(fld.Typ);
|
||||||
}
|
if fld.Tag != nil {
|
||||||
} else {
|
P.separator = tab;
|
||||||
P.Expr(fld.Typ);
|
P.Expr(fld.Tag);
|
||||||
if fld.Tag != nil {
|
}
|
||||||
P.separator = tab;
|
|
||||||
P.Expr(fld.Tag);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -977,7 +995,7 @@ func (P *Printer) DoConstDecl(d *ast.ConstDecl) {
|
|||||||
P.Token(d.Loc, token.CONST);
|
P.Token(d.Loc, token.CONST);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
}
|
}
|
||||||
P.Idents(d.Idents);
|
P.Idents(d.Idents, P.full);
|
||||||
if d.Typ != nil {
|
if d.Typ != nil {
|
||||||
P.separator = blank; // TODO switch to tab? (indentation problem with structs)
|
P.separator = blank; // TODO switch to tab? (indentation problem with structs)
|
||||||
P.Expr(d.Typ);
|
P.Expr(d.Typ);
|
||||||
@ -1009,7 +1027,7 @@ func (P *Printer) DoVarDecl(d *ast.VarDecl) {
|
|||||||
P.Token(d.Loc, token.VAR);
|
P.Token(d.Loc, token.VAR);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
}
|
}
|
||||||
P.Idents(d.Idents);
|
P.Idents(d.Idents, P.full);
|
||||||
if d.Typ != nil {
|
if d.Typ != nil {
|
||||||
P.separator = blank; // TODO switch to tab? (indentation problem with structs)
|
P.separator = blank; // TODO switch to tab? (indentation problem with structs)
|
||||||
P.Expr(d.Typ);
|
P.Expr(d.Typ);
|
||||||
@ -1025,7 +1043,7 @@ func (P *Printer) DoVarDecl(d *ast.VarDecl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) funcDecl(d *ast.FuncDecl, with_body bool) {
|
func (P *Printer) DoFuncDecl(d *ast.FuncDecl) {
|
||||||
P.Token(d.Loc, token.FUNC);
|
P.Token(d.Loc, token.FUNC);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
if recv := d.Recv; recv != nil {
|
if recv := d.Recv; recv != nil {
|
||||||
@ -1041,7 +1059,7 @@ func (P *Printer) funcDecl(d *ast.FuncDecl, with_body bool) {
|
|||||||
}
|
}
|
||||||
P.Expr(d.Ident);
|
P.Expr(d.Ident);
|
||||||
P.Signature(d.Sig);
|
P.Signature(d.Sig);
|
||||||
if with_body && d.Body != nil {
|
if P.full && d.Body != nil {
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Block(d.Body, true);
|
P.Block(d.Body, true);
|
||||||
}
|
}
|
||||||
@ -1049,17 +1067,8 @@ func (P *Printer) funcDecl(d *ast.FuncDecl, with_body bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoFuncDecl(d *ast.FuncDecl) {
|
|
||||||
P.funcDecl(d, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoDeclList(d *ast.DeclList) {
|
func (P *Printer) DoDeclList(d *ast.DeclList) {
|
||||||
if !*def || d.Tok == token.IMPORT || d.Tok == token.VAR {
|
P.Token(d.Loc, d.Tok);
|
||||||
P.Token(d.Loc, d.Tok);
|
|
||||||
} else {
|
|
||||||
P.String(d.Loc, "def");
|
|
||||||
}
|
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
|
|
||||||
// group of parenthesized declarations
|
// group of parenthesized declarations
|
||||||
@ -1090,26 +1099,111 @@ func (P *Printer) Decl(d ast.Decl) {
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Package interface
|
// Package interface
|
||||||
|
|
||||||
// TODO this should be an AST method
|
func stripWhiteSpace(s []byte) []byte {
|
||||||
func isExported(name *ast.Ident) bool {
|
i, j := 0, len(s);
|
||||||
ch, len := utf8.DecodeRuneInString(name.Str, 0);
|
for i < len(s) && s[i] <= ' ' {
|
||||||
return unicode.IsUpper(ch);
|
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.CommentGroup) {
|
||||||
|
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.Program) {
|
func (P *Printer) Interface(p *ast.Program) {
|
||||||
|
P.full = false;
|
||||||
for i := 0; i < len(p.Decls); i++ {
|
for i := 0; i < len(p.Decls); i++ {
|
||||||
switch d := p.Decls[i].(type) {
|
switch d := p.Decls[i].(type) {
|
||||||
|
case *ast.ConstDecl:
|
||||||
|
if hasExportedNames(d.Idents) {
|
||||||
|
P.Printf("<h2>Constants</h2>\n");
|
||||||
|
P.Printf("<p><pre>");
|
||||||
|
P.DoConstDecl(d);
|
||||||
|
P.String(noloc, "");
|
||||||
|
P.Printf("</pre></p>\n");
|
||||||
|
if d.Comment != nil {
|
||||||
|
P.printComment(d.Comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.TypeDecl:
|
||||||
|
if isExported(d.Ident) {
|
||||||
|
P.Printf("<h2>type %s</h2>\n", d.Ident.Str);
|
||||||
|
P.Printf("<p><pre>");
|
||||||
|
P.DoTypeDecl(d);
|
||||||
|
P.String(noloc, "");
|
||||||
|
P.Printf("</pre></p>\n");
|
||||||
|
if d.Comment != nil {
|
||||||
|
P.printComment(d.Comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.VarDecl:
|
||||||
|
if hasExportedNames(d.Idents) {
|
||||||
|
P.Printf("<h2>Variables</h2>\n");
|
||||||
|
P.Printf("<p><pre>");
|
||||||
|
P.DoVarDecl(d);
|
||||||
|
P.String(noloc, "");
|
||||||
|
P.Printf("</pre></p>\n");
|
||||||
|
if d.Comment != nil {
|
||||||
|
P.printComment(d.Comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
if isExported(d.Ident) {
|
if isExported(d.Ident) {
|
||||||
P.Printf("<h2>%s</h2>\n", d.Ident.Str);
|
if d.Recv != nil {
|
||||||
/*
|
P.Printf("<h3>func (");
|
||||||
|
P.Expr(d.Recv.Typ);
|
||||||
|
P.Printf(") %s</h3>\n", d.Ident.Str);
|
||||||
|
} else {
|
||||||
|
P.Printf("<h2>func %s</h2>\n", d.Ident.Str);
|
||||||
|
}
|
||||||
P.Printf("<p><code>");
|
P.Printf("<p><code>");
|
||||||
P.funcDecl(d, false);
|
P.DoFuncDecl(d);
|
||||||
P.String(noloc, "");
|
P.String(noloc, "");
|
||||||
P.Printf("</code></p>");
|
P.Printf("</code></p>\n");
|
||||||
*/
|
if d.Comment != nil {
|
||||||
|
P.printComment(d.Comment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case *ast.DeclList:
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1119,6 +1213,7 @@ func (P *Printer) Interface(p *ast.Program) {
|
|||||||
// Program
|
// Program
|
||||||
|
|
||||||
func (P *Printer) Program(p *ast.Program) {
|
func (P *Printer) Program(p *ast.Program) {
|
||||||
|
P.full = true;
|
||||||
P.Token(p.Loc, token.PACKAGE);
|
P.Token(p.Loc, token.PACKAGE);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Expr(p.Ident);
|
P.Expr(p.Ident);
|
||||||
@ -1140,7 +1235,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func Print(writer io.Write, html bool, prog *ast.Program) {
|
func Print(writer io.Write, prog *ast.Program, html bool) {
|
||||||
// setup
|
// setup
|
||||||
var P Printer;
|
var P Printer;
|
||||||
padchar := byte(' ');
|
padchar := byte(' ');
|
||||||
@ -1152,13 +1247,14 @@ func Print(writer io.Write, html bool, prog *ast.Program) {
|
|||||||
flags |= tabwriter.FilterHTML;
|
flags |= tabwriter.FilterHTML;
|
||||||
}
|
}
|
||||||
text := tabwriter.NewWriter(writer, *tabwidth, 1, padchar, flags);
|
text := tabwriter.NewWriter(writer, *tabwidth, 1, padchar, flags);
|
||||||
P.Init(text, html, prog.Comments);
|
P.Init(text, nil /* prog.Comments */, html);
|
||||||
|
|
||||||
if P.html {
|
if P.html {
|
||||||
err := templ.Apply(text, "<!--", template.Substitution {
|
err := templ.Apply(text, "<!--", template.Substitution {
|
||||||
"PACKAGE-->" : func() { P.Printf("%s", prog.Ident.Str); },
|
"PACKAGE_NAME-->" : func() { P.Printf("%s", prog.Ident.Str); },
|
||||||
"INTERFACE-->" : func() { P.Interface(prog); },
|
"PACKAGE_COMMENT-->": func() { P.printComment(prog.Comment); },
|
||||||
"BODY-->" : func() { P.Program(prog); },
|
"PACKAGE_INTERFACE-->" : func() { P.Interface(prog); },
|
||||||
|
"PACKAGE_BODY-->" : func() { P.Program(prog); },
|
||||||
});
|
});
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("print error - exiting");
|
panic("print error - exiting");
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
|
|
||||||
<h1>package <!--PACKAGE--></h1>
|
<font color=red>THIS SECTION IS CURRENTLY UNDER CONSTRUCTION</font>
|
||||||
|
|
||||||
<!--INTERFACE-->
|
<h1>package <!--PACKAGE_NAME--></h1>
|
||||||
|
<!--PACKAGE_COMMENT-->
|
||||||
|
<!--PACKAGE_INTERFACE-->
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
<h1>Implementation</h1>
|
||||||
<h1>package <!--PACKAGE--></h1>
|
<font color=grey>Comments are currently not shown in the source.</font>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<!--BODY-->
|
<!--PACKAGE_BODY-->
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
</div> <!-- content -->
|
</div> <!-- content -->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user