package AST;
+// ----------------------------------------------------------------------------
+// Lists
+
+export type Element interface {}
+
+
+export type List struct {
+ a *[] Element
+}
+
+
+func (p *List) len() int {
+ return len(p.a);
+}
+
+
+func (p *List) at(i int) Element {
+ return p.a[i];
+}
+
+
+func (p *List) Add (x Element) {
+ a := p.a;
+ n := len(a);
+
+ if n == cap(a) {
+ b := new([] interface {}, 2*n);
+ for i := 0; i < n; i++ {
+ b[i] = a[i];
+ }
+ a = b;
+ }
+
+ a = a[0 : n + 1];
+ a[n] = x;
+ p.a = a;
+}
+
+
+export func NewList() *List {
+ p := new(List);
+ p.a = new([] interface {}, 10);
+ return p;
+}
+
+
+// ----------------------------------------------------------------------------
+// Expressions
export type Expr interface {
- pos() int;
- print();
}
-export type Stat interface {
- pos() int;
- print();
+export type Selector struct {
+ pos int;
+ x Expr;
+ field string;
}
-// ---------------------------------------------------------------------
-// Concrete nodes
+export type Index struct {
+ pos int;
+ x Expr;
+ index Expr;
+}
+
-export type Ident struct {
- pos_ int;
- val_ string;
+export type Pair struct {
+ pos int;
+ x, y Expr;
}
-func (p *Ident) pos() int {
- return p.pos_;
+export type Binary struct {
+ pos int;
+ tok int;
+ x, y Expr;
}
-func (p *Ident) print() {
- print("x"); // TODO fix this
+export type Unary struct {
+ pos int;
+ tok int;
+ x Expr;
+}
+
+
+export type Literal struct {
+ pos int;
+ tok int;
+ val string;
+}
+
+
+// ----------------------------------------------------------------------------
+// Statements
+
+
+// ----------------------------------------------------------------------------
+// Visitor
+
+export type Visitor interface {
+ DoBinary(x *Binary);
+ //DoUnary(x *Unary);
+ //DoLiteral(x *Literal);
}
-// TODO: complete this
+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); }
import Scanner "scanner"
import AST "ast"
+import Printer "printer"
+
export type Parser struct {
+ silent bool;
verbose bool;
indent uint;
scanner *Scanner.Scanner;
}
-func (P *Parser) Open(verbose bool, scanner *Scanner.Scanner, tokchan *<-chan *Scanner.Token) {
- P.verbose = verbose;
+func (P *Parser) Open(silent, verbose bool, scanner *Scanner.Scanner, tokchan *<-chan *Scanner.Token) {
+ P.silent = silent;
+ P.verbose = verbose;
P.indent = 0;
P.scanner = scanner;
P.tokchan = tokchan;
func (P *Parser) ParseDeclaration();
-func (P *Parser) ParseIdent() *AST.Ident {
+func (P *Parser) ParseIdent() *AST.Literal {
P.Trace("Ident");
- ident := new(AST.Ident);
- ident.pos_, ident.val_ = P.pos, "";
+ ident := new(AST.Literal);
+ ident.pos, ident.tok, ident.val = P.pos, Scanner.IDENT, "";
if P.tok == Scanner.IDENT {
- ident.val_ = P.val;
+ ident.val = P.val;
if P.verbose {
P.PrintIndent();
- print("Ident = \"", ident.val_, "\"\n");
+ print("Ident = \"", ident.val, "\"\n");
}
P.Next();
} else {
}
-func (P *Parser) ParseQualifiedIdent(ident *AST.Ident) AST.Expr {
+func (P *Parser) ParseQualifiedIdent(ident *AST.Literal) AST.Expr {
P.Trace("QualifiedIdent");
if ident == nil {
ident = P.ParseIdent();
}
+
+ var x AST.Expr = ident;
+
if P.tok == Scanner.PERIOD {
P.Next();
- ident = P.ParseIdent();
+ ident2 := P.ParseIdent();
+
+ z := new(AST.Selector);
+ z.pos, z.x, z.field = ident.pos, ident, ident2.val;
+ x = z;
}
P.Ecart();
- return ident;
+ return x;
}
// ----------------------------------------------------------------------------
// Expressions
-func (P *Parser) ParseExpressionList() {
+func (P *Parser) ParseExpressionList() *AST.List {
P.Trace("ExpressionList");
-
- P.ParseExpression();
+
+ p := AST.NewList();
+ p.Add(P.ParseExpression());
for P.tok == Scanner.COMMA {
P.Next();
- P.ParseExpression();
+ p.Add(P.ParseExpression());
}
P.Ecart();
+ return p;
}
}
-func (P *Parser) ParseExpressionPair() {
+func (P *Parser) ParseExpressionPair() AST.Expr {
P.Trace("ExpressionPair");
- P.ParseExpression();
+ x := P.ParseExpression();
+ pos := P.pos;
P.Expect(Scanner.COLON);
- P.ParseExpression();
+ y := P.ParseExpression();
+
+ z := new(AST.Pair);
+ z.pos, z.x, z.y = pos, x, y;
P.Ecart();
+ return z;
}
-func (P *Parser) ParseExpressionPairList() {
+func (P *Parser) ParseExpressionPairList() *AST.List {
P.Trace("ExpressionPairList");
- P.ParseExpressionPair();
+ p := AST.NewList();
+ p.Add(P.ParseExpressionPair());
for P.tok == Scanner.COMMA {
- P.ParseExpressionPair();
+ p.Add(P.ParseExpressionPair());
}
P.Ecart();
+ return p;
}
P.Expect(Scanner.RBRACE);
P.Ecart();
- var x AST.Expr;
- return x;
+ return nil;
}
-func (P *Parser) ParseOperand(ident *AST.Ident) AST.Expr {
+func (P *Parser) ParseOperand(ident *AST.Literal) AST.Expr {
P.Trace("Operand");
if ident == nil && P.tok == Scanner.IDENT {
ident = P.ParseIdent();
}
- var x AST.Expr;
+ var z AST.Expr;
if ident != nil {
- // we have an identifier
+ z = ident;
} else {
switch P.tok {
case Scanner.LPAREN:
P.Next();
- x = P.ParseExpression();
+ z = P.ParseExpression();
P.Expect(Scanner.RPAREN);
-
- case Scanner.INT:
- P.Next();
-
- case Scanner.FLOAT:
- P.Next();
- case Scanner.STRING:
+ case Scanner.INT, Scanner.FLOAT, Scanner.STRING:
+ x := new(AST.Literal);
+ x.pos, x.tok, x.val = P.pos, P.tok, P.val;
+ z = x;
P.Next();
case Scanner.FUNC:
- P.ParseFunctionLit();
+ z = P.ParseFunctionLit();
case Scanner.HASH:
P.Next();
P.ParseType();
P.ParseCompositeLit();
+ z = nil;
default:
if P.tok != Scanner.IDENT && P.TryType() {
- P.ParseCompositeLit();
+ z = P.ParseCompositeLit();
} else {
P.Error(P.pos, "operand expected");
P.Next(); // make progress
}
P.Ecart();
- return x;
+ return z;
}
func (P *Parser) ParseSelectorOrTypeGuard(x AST.Expr) AST.Expr {
P.Trace("SelectorOrTypeGuard");
- P.Expect(Scanner.PERIOD);
pos := P.pos;
+ P.Expect(Scanner.PERIOD);
- if P.tok >= Scanner.IDENT {
- P.ParseIdent();
+ if P.tok == Scanner.IDENT {
+ ident := P.ParseIdent();
+
+ z := new(AST.Selector);
+ z.pos, z.x, z.field = pos, x, ident.val;
+ x = z;
+
} else {
P.Expect(Scanner.LPAREN);
P.ParseType();
func (P *Parser) ParseIndexOrSlice(x AST.Expr) AST.Expr {
P.Trace("IndexOrSlice");
+ pos := P.pos;
P.Expect(Scanner.LBRACK);
i := P.ParseExpression();
if P.tok == Scanner.COLON {
P.Next();
j := P.ParseExpression();
+ // TODO: handle this case
}
P.Expect(Scanner.RBRACK);
-
+
+ z := new(AST.Index);
+ z.pos, z.x, z.index = pos, x, i;
+
P.Ecart();
- return x;
+ return z;
}
}
-func (P *Parser) ParsePrimaryExpr(ident *AST.Ident) AST.Expr {
+func (P *Parser) ParsePrimaryExpr(ident *AST.Literal) AST.Expr {
P.Trace("PrimaryExpr");
x := P.ParseOperand(ident);
- for {
+ L: for {
switch P.tok {
case Scanner.PERIOD: x = P.ParseSelectorOrTypeGuard(x);
case Scanner.LBRACK: x = P.ParseIndexOrSlice(x);
case Scanner.LPAREN: x = P.ParseCall(x);
- default: goto exit;
+ default: break L;
}
}
-exit:
P.Ecart();
return x;
}
func (P *Parser) ParseUnaryExpr() AST.Expr {
P.Trace("UnaryExpr");
+ var x AST.Expr;
switch P.tok {
- case Scanner.ADD: fallthrough;
- case Scanner.SUB: fallthrough;
- case Scanner.NOT: fallthrough;
- case Scanner.XOR: fallthrough;
- case Scanner.MUL: fallthrough;
- case Scanner.ARROW: fallthrough;
- case Scanner.AND:
- P.Next();
- x := P.ParseUnaryExpr();
- P.Ecart();
- return x; // TODO fix this
+ case
+ Scanner.ADD, Scanner.SUB,
+ Scanner.NOT, Scanner.XOR,
+ Scanner.MUL, Scanner.ARROW,
+ Scanner.AND:
+ pos, tok := P.pos, P.tok;
+ P.Next();
+ y := P.ParseUnaryExpr();
+
+ x := new(AST.Unary);
+ x.pos, x.tok, x.x = pos, tok, y;
+
+ default:
+ x = P.ParsePrimaryExpr(nil);
}
- x := P.ParsePrimaryExpr(nil);
P.Ecart();
- return x; // TODO fix this
+ return x;
}
}
-func (P *Parser) ParseBinaryExpr(ident *AST.Ident, prec1 int) AST.Expr {
+func (P *Parser) ParseBinaryExpr(ident *AST.Literal, prec1 int) AST.Expr {
P.Trace("BinaryExpr");
var x AST.Expr;
for prec := Precedence(P.tok); prec >= prec1; prec-- {
for Precedence(P.tok) == prec {
+ pos, tok := P.pos, P.tok;
P.Next();
y := P.ParseBinaryExpr(nil, prec + 1);
+
+ z := new(AST.Binary);
+ z.pos, z.tok, z.x, z.y = pos, tok, x, y;
+ x = z;
}
}
// Expressions where the first token may be an identifier which has already been consumed.
-func (P *Parser) ParseIdentExpression(ident *AST.Ident) AST.Expr {
+func (P *Parser) ParseIdentExpression(ident *AST.Literal) AST.Expr {
P.Trace("IdentExpression");
indent := P.indent;
P.Trace("Expression");
x := P.ParseIdentExpression(nil);
+
+ if !P.silent {
+ Printer.Print(x);
+ }
P.Ecart();
return x;