Commit 09bed256 authored by Robert Griesemer's avatar Robert Griesemer

- snapshot of pretty printer status

- parts of AST built and printed
- no formatting yet

R=r
OCL=15727
CL=15727
parent 7c48a394
...@@ -4,14 +4,54 @@ ...@@ -4,14 +4,54 @@
package AST package AST
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Lists // Visitor
export type Element interface {} export type Visitor interface {
// Basics
DoNil(x *Nil);
DoIdent(x *Ident);
// Declarations
DoFuncDecl(x *FuncDecl);
// Expressions
DoBinary(x *Binary);
DoUnary(x *Unary);
DoLiteral(x *Literal);
DoPair(x *Pair);
DoIndex(x *Index);
DoCall(x *Call);
DoSelector(x *Selector);
// Statements
DoBlock(x *Block);
DoExprStat(x *ExprStat);
DoAssignment(x *Assignment);
DoIf(x *If);
DoFor(x *For);
DoSwitch(x *Switch);
DoReturn(x *Return);
// Program
DoProgram(x *Program);
}
// ----------------------------------------------------------------------------
// An AST Node
export type Node interface {
Visit(x Visitor);
}
// ----------------------------------------------------------------------------
// Lists
export type List struct { export type List struct {
a *[] Element a *[] Node
} }
...@@ -20,17 +60,17 @@ func (p *List) len() int { ...@@ -20,17 +60,17 @@ func (p *List) len() int {
} }
func (p *List) at(i int) Element { func (p *List) at(i int) Node {
return p.a[i]; return p.a[i];
} }
func (p *List) Add (x Element) { func (p *List) Add (x Node) {
a := p.a; a := p.a;
n := len(a); n := len(a);
if n == cap(a) { if n == cap(a) {
b := new([] interface {}, 2*n); b := new([] Node, 2*n);
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
b[i] = a[i]; b[i] = a[i];
} }
...@@ -45,15 +85,54 @@ func (p *List) Add (x Element) { ...@@ -45,15 +85,54 @@ func (p *List) Add (x Element) {
export func NewList() *List { export func NewList() *List {
p := new(List); p := new(List);
p.a = new([] interface {}, 10); p.a = new([] Node, 10) [0 : 0];
return p; return p;
} }
// ----------------------------------------------------------------------------
// Basics
export type Nil struct {
// The Node "nil" value
}
export var NIL *Nil = new(Nil);
export type Ident struct {
pos int;
val string;
}
func (x *Nil) Visit(v Visitor) { v.DoNil(x); }
func (x *Ident) Visit(v Visitor) { v.DoIdent(x); }
// ----------------------------------------------------------------------------
// Declarations
export type Decl interface {
Visit(x Visitor);
}
export type FuncDecl struct {
pos int;
ident *Ident;
body *Block;
}
func (x *FuncDecl) Visit(v Visitor) { v.DoFuncDecl(x); }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Expressions // Expressions
export type Expr interface { export type Expr interface {
Visit(x Visitor);
} }
...@@ -71,6 +150,13 @@ export type Index struct { ...@@ -71,6 +150,13 @@ export type Index struct {
} }
export type Call struct {
pos int;
fun Expr;
args *List;
}
export type Pair struct { export type Pair struct {
pos int; pos int;
x, y Expr; x, y Expr;
...@@ -98,20 +184,79 @@ export type Literal struct { ...@@ -98,20 +184,79 @@ 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); }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
export type Stat interface {
Visit(x Visitor);
}
export type Block struct {
pos int;
stats *List;
}
export type ExprStat struct {
expr Expr;
}
export type Assignment struct {
pos int;
tok int;
lhs, rhs *List;
}
export type If struct {
pos int;
cond Expr;
then, else_ *Block;
}
export type For struct {
}
export type Switch struct {
}
export type Return struct {
pos int;
res *List;
}
func (x *Block) Visit(v Visitor) { v.DoBlock(x); }
func (x *ExprStat) Visit(v Visitor) { v.DoExprStat(x); }
func (x *Assignment) Visit(v Visitor) { v.DoAssignment(x); }
func (x *If) Visit(v Visitor) { v.DoIf(x); }
func (x *For) Visit(v Visitor) { v.DoFor(x); }
func (x *Switch) Visit(v Visitor) { v.DoSwitch(x); }
func (x *Return) Visit(v Visitor) { v.DoReturn(x); }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Visitor // Program
export type Visitor interface { export type Program struct {
DoBinary(x *Binary); pos int;
//DoUnary(x *Unary); ident *Ident;
//DoLiteral(x *Literal); decls *List;
} }
func (x *Binary) Visit(v Visitor) { v.DoBinary(x); } func (x *Program) Visit(v Visitor) { v.DoProgram(x); }
//func (x *Unary) Visit(v Visitor) { v.DoUnary(x); }
//func (x *Literal) Visit(v Visitor) { v.DoLiteral(x); }
...@@ -6,11 +6,9 @@ package Parser ...@@ -6,11 +6,9 @@ package Parser
import Scanner "scanner" import Scanner "scanner"
import AST "ast" import AST "ast"
import Printer "printer"
export type Parser struct { export type Parser struct {
silent bool;
verbose bool; verbose bool;
indent uint; indent uint;
scanner *Scanner.Scanner; scanner *Scanner.Scanner;
...@@ -68,8 +66,7 @@ func (P *Parser) Next() { ...@@ -68,8 +66,7 @@ func (P *Parser) Next() {
} }
func (P *Parser) Open(silent, verbose bool, scanner *Scanner.Scanner, tokchan *<-chan *Scanner.Token) { func (P *Parser) Open(verbose bool, scanner *Scanner.Scanner, tokchan *<-chan *Scanner.Token) {
P.silent = silent;
P.verbose = verbose; P.verbose = verbose;
P.indent = 0; P.indent = 0;
P.scanner = scanner; P.scanner = scanner;
...@@ -115,15 +112,15 @@ func (P *Parser) CloseScope() { ...@@ -115,15 +112,15 @@ func (P *Parser) CloseScope() {
func (P *Parser) TryType() bool; func (P *Parser) TryType() bool;
func (P *Parser) ParseExpression() AST.Expr; func (P *Parser) ParseExpression() AST.Expr;
func (P *Parser) TryStatement() bool; func (P *Parser) TryStatement() (AST.Stat, bool);
func (P *Parser) ParseDeclaration(); func (P *Parser) ParseDeclaration() AST.Decl;
func (P *Parser) ParseIdent() *AST.Literal { func (P *Parser) ParseIdent() *AST.Ident {
P.Trace("Ident"); P.Trace("Ident");
ident := new(AST.Literal); ident := new(AST.Ident);
ident.pos, ident.tok, ident.val = P.pos, Scanner.IDENT, ""; ident.pos, ident.val = P.pos, "";
if P.tok == Scanner.IDENT { if P.tok == Scanner.IDENT {
ident.val = P.val; ident.val = P.val;
if P.verbose { if P.verbose {
...@@ -156,7 +153,7 @@ func (P *Parser) ParseIdentList() int { ...@@ -156,7 +153,7 @@ func (P *Parser) ParseIdentList() int {
} }
func (P *Parser) ParseQualifiedIdent(ident *AST.Literal) AST.Expr { func (P *Parser) ParseQualifiedIdent(ident *AST.Ident) AST.Expr {
P.Trace("QualifiedIdent"); P.Trace("QualifiedIdent");
if ident == nil { if ident == nil {
...@@ -444,38 +441,59 @@ func (P *Parser) TryType() bool { ...@@ -444,38 +441,59 @@ func (P *Parser) TryType() bool {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Blocks // Blocks
func (P *Parser) ParseStatement() { func (P *Parser) ParseStatement() AST.Stat {
P.Trace("Statement"); P.Trace("Statement");
if !P.TryStatement() {
stat, ok := P.TryStatement();
if !ok {
P.Error(P.pos, "statement expected"); P.Error(P.pos, "statement expected");
P.Next(); // make progress P.Next(); // make progress
} }
P.Ecart(); P.Ecart();
return stat;
} }
func (P *Parser) ParseStatementList() { func (P *Parser) ParseStatementList() *AST.List {
P.Trace("StatementList"); P.Trace("StatementList");
for P.TryStatement() {
stats := AST.NewList();
for {
stat, ok := P.TryStatement();
if ok {
stats.Add(stat);
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
} else {
break;
}
} }
P.Ecart(); P.Ecart();
return stats;
} }
func (P *Parser) ParseBlock() { func (P *Parser) ParseBlock() *AST.Block {
P.Trace("Block"); P.Trace("Block");
pos := P.pos;
P.Expect(Scanner.LBRACE); P.Expect(Scanner.LBRACE);
P.OpenScope(); P.OpenScope();
var stats *AST.List;
if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON { if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
P.ParseStatementList(); stats = P.ParseStatementList();
} }
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
P.CloseScope(); P.CloseScope();
P.Expect(Scanner.RBRACE); P.Expect(Scanner.RBRACE);
P.Ecart(); P.Ecart();
x := new(AST.Block);
x.pos, x.stats = pos, stats;
return x;
} }
...@@ -570,22 +588,14 @@ func (P *Parser) ParseCompositeLit() AST.Expr { ...@@ -570,22 +588,14 @@ func (P *Parser) ParseCompositeLit() AST.Expr {
} }
func (P *Parser) ParseOperand(ident *AST.Literal) AST.Expr { func (P *Parser) ParseOperand() AST.Expr {
P.Trace("Operand"); P.Trace("Operand");
if ident == nil && P.tok == Scanner.IDENT {
// no look-ahead yet
ident = P.ParseIdent();
}
var z AST.Expr; var z AST.Expr;
if ident != nil {
z = ident;
} else {
switch P.tok { switch P.tok {
case Scanner.IDENT:
z = P.ParseIdent();
case Scanner.LPAREN: case Scanner.LPAREN:
P.Next(); P.Next();
z = P.ParseExpression(); z = P.ParseExpression();
...@@ -615,8 +625,6 @@ func (P *Parser) ParseOperand(ident *AST.Literal) AST.Expr { ...@@ -615,8 +625,6 @@ func (P *Parser) ParseOperand(ident *AST.Literal) AST.Expr {
} }
} }
}
P.Ecart(); P.Ecart();
return z; return z;
} }
...@@ -670,6 +678,8 @@ func (P *Parser) ParseIndexOrSlice(x AST.Expr) AST.Expr { ...@@ -670,6 +678,8 @@ 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.Expr {
P.Trace("Call"); P.Trace("Call");
pos := P.pos;
var args *AST.List = nil;
P.Expect(Scanner.LPAREN); P.Expect(Scanner.LPAREN);
if P.tok != Scanner.RPAREN { if P.tok != Scanner.RPAREN {
// first arguments could be a type if the call is to "new" // first arguments could be a type if the call is to "new"
...@@ -681,24 +691,26 @@ func (P *Parser) ParseCall(x AST.Expr) AST.Expr { ...@@ -681,24 +691,26 @@ func (P *Parser) ParseCall(x AST.Expr) AST.Expr {
if P.tok == Scanner.COMMA { if P.tok == Scanner.COMMA {
P.Next(); P.Next();
if P.tok != Scanner.RPAREN { if P.tok != Scanner.RPAREN {
P.ParseExpressionList(); args = P.ParseExpressionList();
} }
} }
} else { } else {
P.ParseExpressionList(); args = P.ParseExpressionList();
} }
} }
P.Expect(Scanner.RPAREN); P.Expect(Scanner.RPAREN);
P.Ecart(); P.Ecart();
return x; call := new(AST.Call);
call.pos, call.fun, call.args = pos, x, args;
return call;
} }
func (P *Parser) ParsePrimaryExpr(ident *AST.Literal) AST.Expr { func (P *Parser) ParsePrimaryExpr() AST.Expr {
P.Trace("PrimaryExpr"); P.Trace("PrimaryExpr");
x := P.ParseOperand(ident); x := P.ParseOperand();
L: for { L: for {
switch P.tok { switch P.tok {
case Scanner.PERIOD: x = P.ParseSelectorOrTypeGuard(x); case Scanner.PERIOD: x = P.ParseSelectorOrTypeGuard(x);
...@@ -716,7 +728,7 @@ func (P *Parser) ParsePrimaryExpr(ident *AST.Literal) AST.Expr { ...@@ -716,7 +728,7 @@ func (P *Parser) ParsePrimaryExpr(ident *AST.Literal) AST.Expr {
func (P *Parser) ParseUnaryExpr() AST.Expr { func (P *Parser) ParseUnaryExpr() AST.Expr {
P.Trace("UnaryExpr"); P.Trace("UnaryExpr");
var x AST.Expr; var x AST.Expr = AST.NIL;
switch P.tok { switch P.tok {
case case
Scanner.ADD, Scanner.SUB, Scanner.ADD, Scanner.SUB,
...@@ -727,11 +739,12 @@ func (P *Parser) ParseUnaryExpr() AST.Expr { ...@@ -727,11 +739,12 @@ func (P *Parser) ParseUnaryExpr() AST.Expr {
P.Next(); P.Next();
y := P.ParseUnaryExpr(); y := P.ParseUnaryExpr();
x := new(AST.Unary); z := new(AST.Unary);
x.pos, x.tok, x.x = pos, tok, y; z.pos, z.tok, z.x = pos, tok, y;
x = z;
default: default:
x = P.ParsePrimaryExpr(nil); x = P.ParsePrimaryExpr();
} }
P.Ecart(); P.Ecart();
...@@ -759,21 +772,15 @@ func Precedence(tok int) int { ...@@ -759,21 +772,15 @@ func Precedence(tok int) int {
} }
func (P *Parser) ParseBinaryExpr(ident *AST.Literal, prec1 int) AST.Expr { func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr {
P.Trace("BinaryExpr"); P.Trace("BinaryExpr");
var x AST.Expr; x := P.ParseUnaryExpr();
if ident != nil {
x = P.ParsePrimaryExpr(ident);
} else {
x = P.ParseUnaryExpr();
}
for prec := Precedence(P.tok); prec >= prec1; prec-- { for prec := Precedence(P.tok); prec >= prec1; prec-- {
for Precedence(P.tok) == prec { for Precedence(P.tok) == prec {
pos, tok := P.pos, P.tok; pos, tok := P.pos, P.tok;
P.Next(); P.Next();
y := P.ParseBinaryExpr(nil, prec + 1); y := P.ParseBinaryExpr(prec + 1);
z := new(AST.Binary); z := new(AST.Binary);
z.pos, z.tok, z.x, z.y = pos, tok, x, y; z.pos, z.tok, z.x, z.y = pos, tok, x, y;
...@@ -786,12 +793,11 @@ func (P *Parser) ParseBinaryExpr(ident *AST.Literal, prec1 int) AST.Expr { ...@@ -786,12 +793,11 @@ func (P *Parser) ParseBinaryExpr(ident *AST.Literal, prec1 int) AST.Expr {
} }
// Expressions where the first token may be an identifier which has already been consumed. func (P *Parser) ParseExpression() AST.Expr {
func (P *Parser) ParseIdentExpression(ident *AST.Literal) AST.Expr { P.Trace("Expression");
P.Trace("IdentExpression");
indent := P.indent; indent := P.indent;
x := P.ParseBinaryExpr(ident, 1); x := P.ParseBinaryExpr(1);
if indent != P.indent { if indent != P.indent {
panic("imbalanced tracing code (Expression)"); panic("imbalanced tracing code (Expression)");
...@@ -802,59 +808,49 @@ func (P *Parser) ParseIdentExpression(ident *AST.Literal) AST.Expr { ...@@ -802,59 +808,49 @@ func (P *Parser) ParseIdentExpression(ident *AST.Literal) AST.Expr {
} }
func (P *Parser) ParseExpression() AST.Expr {
P.Trace("Expression");
x := P.ParseIdentExpression(nil);
if !P.silent {
Printer.Print(x);
}
P.Ecart();
return x;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
func (P *Parser) ParseSimpleStat() { func (P *Parser) ParseSimpleStat() AST.Stat {
P.Trace("SimpleStat"); P.Trace("SimpleStat");
P.ParseExpressionList(); var stat AST.Stat = AST.NIL;
x := P.ParseExpressionList();
switch P.tok { switch P.tok {
case Scanner.COLON: case Scanner.COLON:
// label declaration // label declaration
P.Next(); // consume ":" P.Next(); // consume ":"
case Scanner.DEFINE: case
// variable declaration Scanner.DEFINE, Scanner.ASSIGN, Scanner.ADD_ASSIGN,
P.Next(); // consume ":=" Scanner.SUB_ASSIGN, Scanner.MUL_ASSIGN, Scanner.QUO_ASSIGN,
P.ParseExpressionList(); Scanner.REM_ASSIGN, Scanner.AND_ASSIGN, Scanner.OR_ASSIGN,
Scanner.XOR_ASSIGN, Scanner.SHL_ASSIGN, Scanner.SHR_ASSIGN:
case Scanner.ASSIGN: fallthrough; pos, tok := P.pos, P.tok;
case Scanner.ADD_ASSIGN: fallthrough;
case Scanner.SUB_ASSIGN: fallthrough;
case Scanner.MUL_ASSIGN: fallthrough;
case Scanner.QUO_ASSIGN: fallthrough;
case Scanner.REM_ASSIGN: fallthrough;
case Scanner.AND_ASSIGN: fallthrough;
case Scanner.OR_ASSIGN: fallthrough;
case Scanner.XOR_ASSIGN: fallthrough;
case Scanner.SHL_ASSIGN: fallthrough;
case Scanner.SHR_ASSIGN:
P.Next(); P.Next();
P.ParseExpressionList(); y := P.ParseExpressionList();
asgn := new(AST.Assignment);
asgn.pos, asgn.tok, asgn.lhs, asgn.rhs = pos, tok, x, y;
stat = asgn;
default: default:
if P.tok == Scanner.INC || P.tok == Scanner.DEC { if P.tok == Scanner.INC || P.tok == Scanner.DEC {
P.Next(); P.Next();
} else {
xstat := new(AST.ExprStat);
if x != nil && x.len() > 0 {
xstat.expr = x.at(0);
} else {
// this is a syntax error
xstat.expr = AST.NIL;
}
stat = xstat;
} }
} }
P.Ecart(); P.Ecart();
return stat;
} }
...@@ -868,15 +864,19 @@ func (P *Parser) ParseGoStat() { ...@@ -868,15 +864,19 @@ func (P *Parser) ParseGoStat() {
} }
func (P *Parser) ParseReturnStat() { func (P *Parser) ParseReturnStat() *AST.Return {
P.Trace("ReturnStat"); P.Trace("ReturnStat");
ret := new(AST.Return);
ret.pos = P.pos;
P.Expect(Scanner.RETURN); P.Expect(Scanner.RETURN);
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE { if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
P.ParseExpressionList(); ret.res = P.ParseExpressionList();
} }
P.Ecart(); P.Ecart();
return ret;
} }
...@@ -892,9 +892,12 @@ func (P *Parser) ParseControlFlowStat(tok int) { ...@@ -892,9 +892,12 @@ func (P *Parser) ParseControlFlowStat(tok int) {
} }
func (P *Parser) ParseIfStat() { func (P *Parser) ParseIfStat() *AST.If {
P.Trace("IfStat"); P.Trace("IfStat");
x := new(AST.If);
x.pos, x.cond = P.pos, AST.NIL;
P.Expect(Scanner.IF); P.Expect(Scanner.IF);
P.OpenScope(); P.OpenScope();
if P.tok != Scanner.LBRACE { if P.tok != Scanner.LBRACE {
...@@ -904,23 +907,27 @@ func (P *Parser) ParseIfStat() { ...@@ -904,23 +907,27 @@ func (P *Parser) ParseIfStat() {
if P.tok == Scanner.SEMICOLON { if P.tok == Scanner.SEMICOLON {
P.Next(); P.Next();
if P.tok != Scanner.LBRACE { if P.tok != Scanner.LBRACE {
P.ParseExpression(); x.cond = P.ParseExpression();
} }
} }
} }
P.ParseBlock(); x.then = P.ParseBlock();
if P.tok == Scanner.ELSE { if P.tok == Scanner.ELSE {
P.Next(); P.Next();
b := new(AST.Block);
b.stats = AST.NewList();
if P.tok == Scanner.IF { if P.tok == Scanner.IF {
P.ParseIfStat(); b.stats.Add(P.ParseIfStat());
} else { } else {
// TODO should be P.ParseBlock() // TODO should be P.ParseBlock()
P.ParseStatement(); b.stats.Add(P.ParseStatement());
} }
x.else_ = b;
} }
P.CloseScope(); P.CloseScope();
P.Ecart(); P.Ecart();
return x;
} }
...@@ -1079,10 +1086,11 @@ func (P *Parser) ParseSelectStat() { ...@@ -1079,10 +1086,11 @@ func (P *Parser) ParseSelectStat() {
} }
func (P *Parser) TryStatement() bool { func (P *Parser) TryStatement() (AST.Stat, bool) {
P.Trace("Statement (try)"); P.Trace("Statement (try)");
indent := P.indent; indent := P.indent;
var stat AST.Stat = AST.NIL;
res := true; res := true;
switch P.tok { switch P.tok {
case Scanner.CONST: fallthrough; case Scanner.CONST: fallthrough;
...@@ -1093,17 +1101,17 @@ func (P *Parser) TryStatement() bool { ...@@ -1093,17 +1101,17 @@ func (P *Parser) TryStatement() bool {
// for now we do not allow local function declarations // for now we do not allow local function declarations
fallthrough; fallthrough;
case Scanner.MUL, Scanner.ARROW, Scanner.IDENT, Scanner.LPAREN: case Scanner.MUL, Scanner.ARROW, Scanner.IDENT, Scanner.LPAREN:
P.ParseSimpleStat(); stat = P.ParseSimpleStat();
case Scanner.GO: case Scanner.GO:
P.ParseGoStat(); P.ParseGoStat();
case Scanner.RETURN: case Scanner.RETURN:
P.ParseReturnStat(); stat = P.ParseReturnStat();
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO: case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
P.ParseControlFlowStat(P.tok); P.ParseControlFlowStat(P.tok);
case Scanner.LBRACE: case Scanner.LBRACE:
P.ParseBlock(); stat = P.ParseBlock();
case Scanner.IF: case Scanner.IF:
P.ParseIfStat(); stat = P.ParseIfStat();
case Scanner.FOR: case Scanner.FOR:
P.ParseForStat(); P.ParseForStat();
case Scanner.SWITCH: case Scanner.SWITCH:
...@@ -1121,7 +1129,7 @@ func (P *Parser) TryStatement() bool { ...@@ -1121,7 +1129,7 @@ func (P *Parser) TryStatement() bool {
panic("imbalanced tracing code (Statement)"); panic("imbalanced tracing code (Statement)");
} }
P.Ecart(); P.Ecart();
return res; return stat, res;
} }
...@@ -1236,12 +1244,12 @@ func (P *Parser) ParseDecl(exported bool, keyword int) { ...@@ -1236,12 +1244,12 @@ func (P *Parser) ParseDecl(exported bool, keyword int) {
// func (recv) ident (params) type // func (recv) ident (params) type
// func (recv) ident (params) (results) // func (recv) ident (params) (results)
func (P *Parser) ParseFuncDecl(exported bool) { func (P *Parser) ParseFuncDecl(exported bool) *AST.FuncDecl {
P.Trace("FuncDecl"); P.Trace("FuncDecl");
pos := P.pos;
P.Expect(Scanner.FUNC); P.Expect(Scanner.FUNC);
P.OpenScope(); P.OpenScope();
P.level--; P.level--;
...@@ -1260,15 +1268,19 @@ func (P *Parser) ParseFuncDecl(exported bool) { ...@@ -1260,15 +1268,19 @@ func (P *Parser) ParseFuncDecl(exported bool) {
P.level++; P.level++;
P.CloseScope(); P.CloseScope();
var body *AST.Block;
if P.tok == Scanner.SEMICOLON { if P.tok == Scanner.SEMICOLON {
// forward declaration // forward declaration
P.Next(); P.Next();
} else { } else {
P.ParseBlock(); body = P.ParseBlock();
} }
P.Ecart(); P.Ecart();
x := new(AST.FuncDecl);
x.pos, x.ident, x.body = pos, ident, body;
return x;
} }
...@@ -1296,7 +1308,7 @@ func (P *Parser) ParseExportDecl() { ...@@ -1296,7 +1308,7 @@ func (P *Parser) ParseExportDecl() {
} }
func (P *Parser) ParseDeclaration() { func (P *Parser) ParseDeclaration() AST.Decl {
P.Trace("Declaration"); P.Trace("Declaration");
indent := P.indent; indent := P.indent;
...@@ -1310,11 +1322,12 @@ func (P *Parser) ParseDeclaration() { ...@@ -1310,11 +1322,12 @@ func (P *Parser) ParseDeclaration() {
P.Next(); P.Next();
} }
var x AST.Decl = AST.NIL;
switch P.tok { switch P.tok {
case Scanner.CONST, Scanner.TYPE, Scanner.VAR: case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
P.ParseDecl(exported, P.tok); P.ParseDecl(exported, P.tok);
case Scanner.FUNC: case Scanner.FUNC:
P.ParseFuncDecl(exported); x = P.ParseFuncDecl(exported);
case Scanner.EXPORT: case Scanner.EXPORT:
if exported { if exported {
P.Error(P.pos, "cannot mark export declaration for export"); P.Error(P.pos, "cannot mark export declaration for export");
...@@ -1334,20 +1347,23 @@ func (P *Parser) ParseDeclaration() { ...@@ -1334,20 +1347,23 @@ func (P *Parser) ParseDeclaration() {
panic("imbalanced tracing code (Declaration)"); panic("imbalanced tracing code (Declaration)");
} }
P.Ecart(); P.Ecart();
return x;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Program // Program
func (P *Parser) ParseProgram() { func (P *Parser) ParseProgram() *AST.Program {
P.Trace("Program"); P.Trace("Program");
P.OpenScope(); P.OpenScope();
pos := P.pos;
P.Expect(Scanner.PACKAGE); P.Expect(Scanner.PACKAGE);
obj := P.ParseIdent(); ident := P.ParseIdent();
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
decls := AST.NewList();
{ P.OpenScope(); { P.OpenScope();
if P.level != 0 { if P.level != 0 {
panic("incorrect scope level"); panic("incorrect scope level");
...@@ -1359,7 +1375,7 @@ func (P *Parser) ParseProgram() { ...@@ -1359,7 +1375,7 @@ func (P *Parser) ParseProgram() {
} }
for P.tok != Scanner.EOF { for P.tok != Scanner.EOF {
P.ParseDeclaration(); decls.Add(P.ParseDeclaration());
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
} }
...@@ -1371,4 +1387,8 @@ func (P *Parser) ParseProgram() { ...@@ -1371,4 +1387,8 @@ func (P *Parser) ParseProgram() {
P.CloseScope(); P.CloseScope();
P.Ecart(); P.Ecart();
x := new(AST.Program);
x.pos, x.ident, x.decls = pos, ident, decls;
return x;
} }
...@@ -54,8 +54,11 @@ func main() { ...@@ -54,8 +54,11 @@ func main() {
} }
parser := new(Parser.Parser); parser := new(Parser.Parser);
parser.Open(silent.BVal(), verbose.BVal(), scanner, tstream); parser.Open(verbose.BVal(), scanner, tstream);
parser.ParseProgram(); prog := parser.ParseProgram();
if !silent.BVal() {
Printer.Print(prog);
}
} }
} }
...@@ -8,58 +8,192 @@ import Scanner "scanner" ...@@ -8,58 +8,192 @@ import Scanner "scanner"
import AST "ast" import AST "ast"
type Printer struct { type Printer /* implements AST.Visitor */ struct {
indent int;
} }
func (P *Printer) Print(s string) { func (P *Printer) String(s string) {
print(s); print(s);
} }
func (P *Printer) PrintExpr(x AST.Expr) { func (P *Printer) Print(x AST.Node) {
/* x.Visit(P);
if x == nil { }
P.Print("<nil>");
return;
func (P *Printer) PrintExprList(p *AST.List) {
if p != nil {
for i := 0; i < p.len(); i++ {
if i > 0 {
P.String(", ");
} }
P.Print(p.at(i));
}
}
}
switch x.tok { // ----------------------------------------------------------------------------
case Scanner.IDENT: // Basics
P.Print(x.val);
case Scanner.INT, Scanner.FLOAT, Scanner.STRING: func (P *Printer) DoNil(x *AST.Nil) {
P.Print(x.val); P.String("?\n");
}
case Scanner.PERIOD:
P.PrintExpr(x.x);
P.Print(Scanner.TokenName(x.tok));
P.PrintExpr(x.y);
case Scanner.LBRACK: func (P *Printer) DoIdent(x *AST.Ident) {
P.PrintExpr(x.x); P.String(x.val);
P.Print("["); }
P.PrintExpr(x.y);
P.Print("]");
default:
// unary or binary expression // ----------------------------------------------------------------------------
print("("); // Declarations
if x.x != nil {
P.PrintExpr(x.x); func (P *Printer) DoBlock(x *AST.Block);
func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
P.String("func ");
P.DoIdent(x.ident);
P.String("(... something here ...) ");
if x.body != nil {
P.DoBlock(x.body);
} else {
P.String(";\n");
} }
P.Print(" " + Scanner.TokenName(x.tok) + " "); }
P.PrintExpr(x.y);
// ----------------------------------------------------------------------------
// Expressions
func (P *Printer) DoBinary(x *AST.Binary) {
print("(");
P.Print(x.x);
P.String(" " + Scanner.TokenName(x.tok) + " ");
P.Print(x.y);
print(")"); print(")");
}
func (P *Printer) DoUnary(x *AST.Unary) {
P.String(Scanner.TokenName(x.tok));
P.Print(x.x);
}
func (P *Printer) DoLiteral(x *AST.Literal) {
P.String(x.val);
}
func (P *Printer) DoPair(x *AST.Pair) {
P.Print(x.x);
P.String(" : ");
P.Print(x.y);
}
func (P *Printer) DoIndex(x *AST.Index) {
P.Print(x.x);
P.String("[");
P.Print(x.index);
P.String("]");
}
func (P *Printer) DoCall(x *AST.Call) {
P.Print(x.fun);
P.String("(");
P.PrintExprList(x.args);
P.String(")");
}
func (P *Printer) DoSelector(x *AST.Selector) {
P.Print(x.x);
P.String(".");
P.String(x.field);
}
// ----------------------------------------------------------------------------
// Statements
func (P *Printer) DoBlock(x *AST.Block) {
if x == nil || x.stats == nil {
P.String("\n");
return;
}
P.String("{\n");
P.indent++;
for i := 0; i < x.stats.len(); i++ {
P.Print(x.stats.at(i));
P.String("\n");
} }
*/ P.indent--;
P.String("}\n");
} }
export func Print(x AST.Expr) { func (P *Printer) DoExprStat(x *AST.ExprStat) {
P.Print(x.expr);
}
func (P *Printer) DoAssignment(x *AST.Assignment) {
P.PrintExprList(x.lhs);
P.String(" " + Scanner.TokenName(x.tok) + " ");
P.PrintExprList(x.rhs);
}
func (P *Printer) DoIf(x *AST.If) {
P.String("if ");
P.Print(x.cond);
P.DoBlock(x.then);
if x.else_ != nil {
P.String("else ");
P.DoBlock(x.else_);
}
}
func (P *Printer) DoFor(x *AST.For) {
}
func (P *Printer) DoSwitch(x *AST.Switch) {
}
func (P *Printer) DoReturn(x *AST.Return) {
P.String("return ");
P.PrintExprList(x.res);
}
// ----------------------------------------------------------------------------
// Program
func (P *Printer) DoProgram(x *AST.Program) {
P.String("package ");
P.DoIdent(x.ident);
P.String("\n");
for i := 0; i < x.decls.len(); i++ {
P.Print(x.decls.at(i));
}
}
// ----------------------------------------------------------------------------
// Driver
export func Print(x AST.Node) {
var P Printer; var P Printer;
print("expr = "); (&P).Print(x);
(&P).PrintExpr(x);
print("\n"); print("\n");
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment