diff --git a/usr/gri/pretty/ast.go b/usr/gri/pretty/ast.go index 7cbd05c5c78826e96ff260f62db32521bfb27688..b8839852a4020573eb8fafb5d5d7d40a1e87213d 100644 --- a/usr/gri/pretty/ast.go +++ b/usr/gri/pretty/ast.go @@ -40,7 +40,9 @@ export type Visitor interface { DoIndex(x *Index); DoCall(x *Call); DoSelector(x *Selector); - + DoCompositeLit(x *CompositeLit); + DoFunctionLit(x *FunctionLit); + // Statements DoLabel(x *Label); DoBlock(x *Block); @@ -167,9 +169,16 @@ export type MapType struct { } +export const /* chan mode */ ( + FULL = iota; + RECV; + SEND; +) + export type ChannelType struct { pos int; // position of "chan" or "<-" (if before "chan") elt Type; + mode int; } @@ -324,13 +333,29 @@ export type Literal struct { } -func (x *Binary) Visit(v Visitor) { v.DoBinary(x); } -func (x *Unary) Visit(v Visitor) { v.DoUnary(x); } -func (x *Literal) Visit(v Visitor) { v.DoLiteral(x); } -func (x *Pair) Visit(v Visitor) { v.DoPair(x); } -func (x *Index) Visit(v Visitor) { v.DoIndex(x); } -func (x *Call) Visit(v Visitor) { v.DoCall(x); } -func (x *Selector) Visit(v Visitor) { v.DoSelector(x); } +export type CompositeLit struct { + pos int; // position of "{" + typ Type; + vals *List // list of Expr +} + + +export type FunctionLit struct { + pos int; // position of "func" + typ *FunctionType; + body *Block; +} + + +func (x *Binary) Visit(v Visitor) { v.DoBinary(x); } +func (x *Unary) Visit(v Visitor) { v.DoUnary(x); } +func (x *Literal) Visit(v Visitor) { v.DoLiteral(x); } +func (x *Pair) Visit(v Visitor) { v.DoPair(x); } +func (x *Index) Visit(v Visitor) { v.DoIndex(x); } +func (x *Call) Visit(v Visitor) { v.DoCall(x); } +func (x *Selector) Visit(v Visitor) { v.DoSelector(x); } +func (x *CompositeLit) Visit(v Visitor) { v.DoCompositeLit(x); } +func (x *FunctionLit) Visit(v Visitor) { v.DoFunctionLit(x); } // ---------------------------------------------------------------------------- diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index c20f8f8d7cfdb232b4e1d2ffd3b529baedc57ad5..8bca136e0dcd4e1cae7ddeccab3811436f3e0767 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -212,6 +212,7 @@ func (P *Parser) ParseArrayType() *AST.ArrayType { typ := new(AST.ArrayType); typ.pos = P.pos; + typ.len_ = AST.NIL; P.Expect(Scanner.LBRACK); if P.tok != Scanner.RBRACK { @@ -231,15 +232,18 @@ func (P *Parser) ParseChannelType() *AST.ChannelType { typ := new(AST.ChannelType); typ.pos = P.pos; + typ.mode = AST.FULL; if P.tok == Scanner.CHAN { P.Next(); if P.tok == Scanner.ARROW { P.Next(); + typ.mode = AST.SEND; } } else { P.Expect(Scanner.ARROW); P.Expect(Scanner.CHAN); + typ.mode = AST.RECV; } typ.elt = P.ParseVarType(); @@ -532,91 +536,106 @@ func (P *Parser) ParseBlock() *AST.Block { // ---------------------------------------------------------------------------- // Expressions -func (P *Parser) ParseExpressionList() *AST.List { +func (P *Parser) ParseExpressionList(list *AST.List) { P.Trace("ExpressionList"); - p := AST.NewList(); - p.Add(P.ParseExpression()); + list.Add(P.ParseExpression()); for P.tok == Scanner.COMMA { P.Next(); - p.Add(P.ParseExpression()); + list.Add(P.ParseExpression()); } P.Ecart(); - return p; } -func (P *Parser) ParseFunctionLit() AST.Expr { +func (P *Parser) ParseNewExpressionList() *AST.List { + list := AST.NewList(); + P.ParseExpressionList(list); + return list; +} + + +func (P *Parser) ParseFunctionLit() *AST.FunctionLit { P.Trace("FunctionLit"); + fun := new(AST.FunctionLit); + fun.pos = P.pos; + P.Expect(Scanner.FUNC); - P.ParseFunctionType(); - P.ParseBlock(); + fun.typ = P.ParseFunctionType(); + fun.body = P.ParseBlock(); P.Ecart(); - var x AST.Expr; - return x; + return fun; } func (P *Parser) ParseExpressionPair() AST.Expr { P.Trace("ExpressionPair"); - x := P.ParseExpression(); - pos := P.pos; + p := new(AST.Pair); + p.x = P.ParseExpression(); + p.pos = P.pos; P.Expect(Scanner.COLON); - y := P.ParseExpression(); - - z := new(AST.Pair); - z.pos, z.x, z.y = pos, x, y; + p.y = P.ParseExpression(); P.Ecart(); - return z; + return p; } -func (P *Parser) ParseExpressionPairList() *AST.List { +func (P *Parser) ParseExpressionPairList(list *AST.List) { P.Trace("ExpressionPairList"); - p := AST.NewList(); - p.Add(P.ParseExpressionPair()); + list.Add(P.ParseExpressionPair()); for P.tok == Scanner.COMMA { - p.Add(P.ParseExpressionPair()); + list.Add(P.ParseExpressionPair()); } P.Ecart(); - return p; } -func (P *Parser) ParseCompositeLit() AST.Expr { +func (P *Parser) ParseCompositeLit(typ AST.Type) AST.Expr { P.Trace("CompositeLit"); + lit := new(AST.CompositeLit); + lit.pos = P.pos; + lit.typ = typ; + lit.vals = AST.NewList(); + P.Expect(Scanner.LBRACE); // TODO: should allow trailing ',' if P.tok != Scanner.RBRACE { - P.ParseExpression(); + x := P.ParseExpression(); if P.tok == Scanner.COMMA { P.Next(); + lit.vals.Add(x); if P.tok != Scanner.RBRACE { - P.ParseExpressionList(); + P.ParseExpressionList(lit.vals); } } else if P.tok == Scanner.COLON { + p := new(AST.Pair); + p.pos = P.pos; + p.x = x; P.Next(); - P.ParseExpression(); + p.y = P.ParseExpression(); + lit.vals.Add(p); if P.tok == Scanner.COMMA { P.Next(); if P.tok != Scanner.RBRACE { - P.ParseExpressionPairList(); + P.ParseExpressionPairList(lit.vals); } } + } else { + lit.vals.Add(x); } } P.Expect(Scanner.RBRACE); P.Ecart(); - return nil; + return lit; } @@ -645,15 +664,15 @@ func (P *Parser) ParseOperand() AST.Expr { case Scanner.HASH: P.Next(); - P.ParseType(); - P.ParseCompositeLit(); + typ := P.ParseType(); + P.ParseCompositeLit(typ); op = AST.NIL; default: if P.tok != Scanner.IDENT { typ, ok := P.TryType(); if ok { - op = P.ParseCompositeLit(); + op = P.ParseCompositeLit(typ); break; } } @@ -712,11 +731,14 @@ func (P *Parser) ParseIndexOrSlice(x AST.Expr) AST.Expr { } -func (P *Parser) ParseCall(x AST.Expr) AST.Expr { +func (P *Parser) ParseCall(x AST.Expr) *AST.Call { P.Trace("Call"); - pos := P.pos; - var args *AST.List = nil; + call := new(AST.Call); + call.pos = P.pos; + call.fun = x; + call.args = nil; + P.Expect(Scanner.LPAREN); if P.tok != Scanner.RPAREN { // first arguments could be a type if the call is to "new" @@ -727,24 +749,24 @@ func (P *Parser) ParseCall(x AST.Expr) AST.Expr { if P.tok != Scanner.IDENT && P.tok != Scanner.LPAREN { typ, ok := P.TryType(); if ok { + call.args = AST.NewList(); + call.args.Add(typ); if P.tok == Scanner.COMMA { P.Next(); if P.tok != Scanner.RPAREN { - args = P.ParseExpressionList(); + P.ParseExpressionList(call.args); } } } else { - args = P.ParseExpressionList(); + call.args = P.ParseNewExpressionList(); } } else { - args = P.ParseExpressionList(); + call.args = P.ParseNewExpressionList(); } } P.Expect(Scanner.RPAREN); P.Ecart(); - call := new(AST.Call); - call.pos, call.fun, call.args = pos, x, args; return call; } @@ -837,7 +859,7 @@ func (P *Parser) ParseSimpleStat() AST.Stat { P.Trace("SimpleStat"); var stat AST.Stat = AST.NIL; - x := P.ParseExpressionList(); + x := P.ParseNewExpressionList(); switch P.tok { case Scanner.COLON: @@ -860,7 +882,7 @@ func (P *Parser) ParseSimpleStat() AST.Stat { Scanner.XOR_ASSIGN, Scanner.SHL_ASSIGN, Scanner.SHR_ASSIGN: pos, tok := P.pos, P.tok; P.Next(); - y := P.ParseExpressionList(); + y := P.ParseNewExpressionList(); a := new(AST.Assignment); a.pos, a.tok, a.lhs, a.rhs = pos, tok, x, y; stat = a; @@ -915,7 +937,7 @@ func (P *Parser) ParseReturnStat() *AST.ReturnStat { P.Expect(Scanner.RETURN); if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE { - stat.res = P.ParseExpressionList(); + stat.res = P.ParseNewExpressionList(); } P.Ecart(); @@ -1020,7 +1042,7 @@ func (P *Parser) ParseCase() *AST.CaseClause { if P.tok == Scanner.CASE { P.Next(); - clause.exprs = P.ParseExpressionList(); + clause.exprs = P.ParseNewExpressionList(); } else { P.Expect(Scanner.DEFAULT); } @@ -1218,6 +1240,7 @@ func (P *Parser) ParseConstSpec(exported bool) *AST.ConstDecl { decl.ident = P.ParseIdent(); var ok bool; decl.typ, ok = P.TryType(); + decl.val = AST.NIL; if P.tok == Scanner.ASSIGN { P.Next(); @@ -1248,12 +1271,13 @@ func (P *Parser) ParseVarSpec(exported bool) *AST.VarDecl { decl.idents = P.ParseIdentList(); if P.tok == Scanner.ASSIGN { P.Next(); - decl.vals = P.ParseExpressionList(); + decl.typ = AST.NIL; + decl.vals = P.ParseNewExpressionList(); } else { decl.typ = P.ParseVarType(); if P.tok == Scanner.ASSIGN { P.Next(); - decl.vals = P.ParseExpressionList(); + decl.vals = P.ParseNewExpressionList(); } } diff --git a/usr/gri/pretty/printer.go b/usr/gri/pretty/printer.go index 7ab363da5b5b2e7b045b3d878008cc276aae5884..52572cedd9860fe3c3b9e4c6981648cf51f5187d 100644 --- a/usr/gri/pretty/printer.go +++ b/usr/gri/pretty/printer.go @@ -107,7 +107,11 @@ func (P *Printer) DoMapType(x *AST.MapType) { func (P *Printer) DoChannelType(x *AST.ChannelType) { - P.String("chan "); + switch x.mode { + case AST.FULL: P.String("chan "); + case AST.RECV: P.String("<-chan "); + case AST.SEND: P.String("chan <- "); + } P.Print(x.elt); } @@ -226,8 +230,8 @@ func (P *Printer) DoDeclaration(x *AST.Declaration) { if i > 0 { P.NewLine(0); } - //print("*** i = ", i, "\n"); P.Print(x.decls.at(i)); + P.String(";"); } P.NewLine(-1); P.String(")"); @@ -300,6 +304,22 @@ func (P *Printer) DoSelector(x *AST.Selector) { } +func (P *Printer) DoCompositeLit(x *AST.CompositeLit) { + P.Print(x.typ); + P.String("{"); + P.PrintList(x.vals); + P.String("}"); +} + + +func (P *Printer) DoFunctionLit(x *AST.FunctionLit) { + P.String("func "); + P.Print(x.typ); + P.String(" "); + P.Print(x.body); +} + + // ---------------------------------------------------------------------------- // Statements @@ -320,8 +340,10 @@ func (P *Printer) DoBlock(x *AST.Block) { func (P *Printer) DoLabel(x *AST.Label) { + P.NewLine(-1); P.Print(x.ident); P.String(":"); + P.indent++; } diff --git a/usr/gri/pretty/scanner.go b/usr/gri/pretty/scanner.go index 60dfa1c6219fdfd37ce3b1810d7cdd34be7d508d..02f5e56fe985fa37869cfd0342eef1420ceba68a 100644 --- a/usr/gri/pretty/scanner.go +++ b/usr/gri/pretty/scanner.go @@ -794,14 +794,14 @@ export type Token struct { func (S *Scanner) TokenStream() *<-chan *Token { - ch := new(chan *Token, 100); + ch := new(chan *Token, 100); go func(S *Scanner, ch *chan <- *Token) { for { t := new(Token); t.tok, t.pos, t.val = S.Scan(); ch <- t; if t.tok == EOF { - break; + break; } } }(S, ch);