mirror of
https://github.com/golang/go
synced 2024-11-22 20:24:47 -07:00
- expanded parsing heuristics to deal with new(T, ...)
- fixed an issue with select - added all bugs and fixedbugs tests that are syntactically correct to the test suite - minor cosmetic changes R=r OCL=17759 CL=17759
This commit is contained in:
parent
8327b54169
commit
816c1cefff
@ -8,7 +8,7 @@ import Scanner "scanner"
|
|||||||
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Node interface {};
|
Any interface {};
|
||||||
Type struct;
|
Type struct;
|
||||||
Expr struct;
|
Expr struct;
|
||||||
Stat struct;
|
Stat struct;
|
||||||
@ -23,7 +23,7 @@ type (
|
|||||||
// Thus, empty lists can be represented by nil.
|
// Thus, empty lists can be represented by nil.
|
||||||
|
|
||||||
export type List struct {
|
export type List struct {
|
||||||
a *[] Node;
|
a *[] Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -33,22 +33,22 @@ func (p *List) len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p *List) at(i int) Node {
|
func (p *List) at(i int) Any {
|
||||||
return p.a[i];
|
return p.a[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p *List) set(i int, x Node) {
|
func (p *List) set(i int, x Any) {
|
||||||
p.a[i] = x;
|
p.a[i] = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p *List) Add (x Node) {
|
func (p *List) Add (x Any) {
|
||||||
a := p.a;
|
a := p.a;
|
||||||
n := len(a);
|
n := len(a);
|
||||||
|
|
||||||
if n == cap(a) {
|
if n == cap(a) {
|
||||||
b := new([] Node, 2*n);
|
b := new([] Any, 2*n);
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
b[i] = a[i];
|
b[i] = a[i];
|
||||||
}
|
}
|
||||||
@ -63,16 +63,24 @@ func (p *List) Add (x Node) {
|
|||||||
|
|
||||||
export func NewList() *List {
|
export func NewList() *List {
|
||||||
p := new(List);
|
p := new(List);
|
||||||
p.a = new([] Node, 10) [0 : 0];
|
p.a = new([] Any, 10) [0 : 0];
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// All nodes have a source position and and token.
|
||||||
|
|
||||||
|
export type Node struct {
|
||||||
|
pos, tok int;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Expressions
|
// Expressions
|
||||||
|
|
||||||
export type Expr struct {
|
export type Expr struct {
|
||||||
pos, tok int;
|
Node;
|
||||||
x, y *Expr; // binary (x, y) and unary (y) expressions
|
x, y *Expr; // binary (x, y) and unary (y) expressions
|
||||||
// TODO find a more space efficient way to hold these
|
// TODO find a more space efficient way to hold these
|
||||||
s string; // identifiers and literals
|
s string; // identifiers and literals
|
||||||
@ -124,7 +132,7 @@ export const /* channel mode */ (
|
|||||||
|
|
||||||
|
|
||||||
export type Type struct {
|
export type Type struct {
|
||||||
pos, tok int;
|
Node;
|
||||||
expr *Expr; // type name, array length
|
expr *Expr; // type name, array length
|
||||||
mode int; // channel mode
|
mode int; // channel mode
|
||||||
key *Type; // receiver type, map key
|
key *Type; // receiver type, map key
|
||||||
@ -171,7 +179,7 @@ export var BadType = NewType(0, Scanner.ILLEGAL);
|
|||||||
// Statements
|
// Statements
|
||||||
|
|
||||||
export type Stat struct {
|
export type Stat struct {
|
||||||
pos, tok int;
|
Node;
|
||||||
init, post *Stat;
|
init, post *Stat;
|
||||||
expr *Expr;
|
expr *Expr;
|
||||||
block *List;
|
block *List;
|
||||||
@ -193,7 +201,7 @@ export var BadStat = NewStat(0, Scanner.ILLEGAL);
|
|||||||
// Declarations
|
// Declarations
|
||||||
|
|
||||||
export type Decl struct {
|
export type Decl struct {
|
||||||
pos, tok int;
|
Node;
|
||||||
exported bool;
|
exported bool;
|
||||||
ident *Expr; // nil for ()-style declarations
|
ident *Expr; // nil for ()-style declarations
|
||||||
typ *Type;
|
typ *Type;
|
||||||
|
@ -93,7 +93,7 @@ func (P *Parser) Open(verbose, sixg bool, scanner *Scanner.Scanner, tokchan *<-c
|
|||||||
P.comments = AST.NewList();
|
P.comments = AST.NewList();
|
||||||
|
|
||||||
P.Next();
|
P.Next();
|
||||||
P.expr_lev = 1;
|
P.expr_lev = 0;
|
||||||
P.scope_lev = 0;
|
P.scope_lev = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,15 +631,39 @@ func (P *Parser) ParseFunctionLit() *AST.Expr {
|
|||||||
x := AST.NewLit(P.pos, Scanner.FUNC, "");
|
x := AST.NewLit(P.pos, Scanner.FUNC, "");
|
||||||
P.Expect(Scanner.FUNC);
|
P.Expect(Scanner.FUNC);
|
||||||
x.t = P.ParseFunctionType();
|
x.t = P.ParseFunctionType();
|
||||||
|
P.expr_lev++;
|
||||||
P.scope_lev++;
|
P.scope_lev++;
|
||||||
x.block = P.ParseBlock();
|
x.block = P.ParseBlock();
|
||||||
P.scope_lev--;
|
P.scope_lev--;
|
||||||
|
P.expr_lev--;
|
||||||
|
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
func (P *Parser) ParseNewCall() *AST.Expr {
|
||||||
|
P.Trace("NewCall");
|
||||||
|
|
||||||
|
x := AST.NewExpr(P.pos, Scanner.NEW, nil, nil);
|
||||||
|
P.Next();
|
||||||
|
P.Expect(Scanner.LPAREN);
|
||||||
|
P.expr_lev++;
|
||||||
|
x.t = P.ParseType();
|
||||||
|
if P.tok == Scanner.COMMA {
|
||||||
|
P.Next();
|
||||||
|
x.y = P.ParseExpressionList();
|
||||||
|
}
|
||||||
|
P.expr_lev--;
|
||||||
|
P.Expect(Scanner.RPAREN);
|
||||||
|
|
||||||
|
P.Ecart();
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) ParseOperand() *AST.Expr {
|
func (P *Parser) ParseOperand() *AST.Expr {
|
||||||
P.Trace("Operand");
|
P.Trace("Operand");
|
||||||
|
|
||||||
@ -668,7 +692,12 @@ func (P *Parser) ParseOperand() *AST.Expr {
|
|||||||
|
|
||||||
case Scanner.FUNC:
|
case Scanner.FUNC:
|
||||||
x = P.ParseFunctionLit();
|
x = P.ParseFunctionLit();
|
||||||
|
|
||||||
|
/*
|
||||||
|
case Scanner.NEW:
|
||||||
|
x = P.ParseNewCall();
|
||||||
|
*/
|
||||||
|
|
||||||
default:
|
default:
|
||||||
t := P.TryType();
|
t := P.TryType();
|
||||||
if t != nil {
|
if t != nil {
|
||||||
@ -709,7 +738,9 @@ func (P *Parser) ParseIndex(x *AST.Expr) *AST.Expr {
|
|||||||
|
|
||||||
pos := P.pos;
|
pos := P.pos;
|
||||||
P.Expect(Scanner.LBRACK);
|
P.Expect(Scanner.LBRACK);
|
||||||
|
P.expr_lev++;
|
||||||
i := P.ParseExpression(0);
|
i := P.ParseExpression(0);
|
||||||
|
P.expr_lev--;
|
||||||
P.Expect(Scanner.RBRACK);
|
P.Expect(Scanner.RBRACK);
|
||||||
|
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
@ -719,25 +750,35 @@ func (P *Parser) ParseIndex(x *AST.Expr) *AST.Expr {
|
|||||||
|
|
||||||
func (P *Parser) ParseBinaryExpr(prec1 int) *AST.Expr
|
func (P *Parser) ParseBinaryExpr(prec1 int) *AST.Expr
|
||||||
|
|
||||||
func (P *Parser) ParseCall(x *AST.Expr) *AST.Expr {
|
func (P *Parser) ParseCall(x0 *AST.Expr) *AST.Expr {
|
||||||
P.Trace("Call");
|
P.Trace("Call");
|
||||||
|
|
||||||
x = P.NewExpr(P.pos, Scanner.LPAREN, x, nil);
|
x := P.NewExpr(P.pos, Scanner.LPAREN, x0, nil);
|
||||||
P.Expect(Scanner.LPAREN);
|
P.Expect(Scanner.LPAREN);
|
||||||
if P.tok != Scanner.RPAREN {
|
if P.tok != Scanner.RPAREN {
|
||||||
// the very first argument may be a type if the function called is new()
|
P.expr_lev++;
|
||||||
// call ParseBinaryExpr() which allows type expressions (instead of ParseExpression)
|
var t *AST.Type;
|
||||||
y := P.ParseBinaryExpr(1);
|
if x0.tok == Scanner.IDENT && x0.s == "new" {
|
||||||
if P.tok == Scanner.COMMA {
|
// heuristic: assume it's a new(T, ...) call, try to parse a type
|
||||||
pos := P.pos;
|
t = P.TryType();
|
||||||
P.Next();
|
|
||||||
z := P.ParseExpressionList();
|
|
||||||
// create list manually because NewExpr checks for type expressions
|
|
||||||
z = P.NewExpr(pos, Scanner.COMMA, nil, z);
|
|
||||||
z.x = y;
|
|
||||||
y = z;
|
|
||||||
}
|
}
|
||||||
x.y = y;
|
if t != nil {
|
||||||
|
// we found a type
|
||||||
|
x.y = AST.NewTypeExpr(t);
|
||||||
|
if P.tok == Scanner.COMMA {
|
||||||
|
pos := P.pos;
|
||||||
|
P.Next();
|
||||||
|
y := P.ParseExpressionList();
|
||||||
|
// create list manually because NewExpr checks for type expressions
|
||||||
|
z := AST.NewExpr(pos, Scanner.COMMA, nil, y);
|
||||||
|
z.x = x.y;
|
||||||
|
x.y = z;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// normal argument list
|
||||||
|
x.y = P.ParseExpressionList();
|
||||||
|
}
|
||||||
|
P.expr_lev--;
|
||||||
}
|
}
|
||||||
P.Expect(Scanner.RPAREN);
|
P.Expect(Scanner.RPAREN);
|
||||||
|
|
||||||
@ -817,10 +858,10 @@ func (P *Parser) ParsePrimaryExpr() *AST.Expr {
|
|||||||
case Scanner.LPAREN: x = P.ParseCall(x);
|
case Scanner.LPAREN: x = P.ParseCall(x);
|
||||||
case Scanner.LBRACE:
|
case Scanner.LBRACE:
|
||||||
// assume a composite literal only if x could be a type
|
// assume a composite literal only if x could be a type
|
||||||
// and if we are not inside control clause (expr_lev > 0)
|
// and if we are not inside control clause (expr_lev >= 0)
|
||||||
// (composites inside control clauses must be parenthesized)
|
// (composites inside control clauses must be parenthesized)
|
||||||
var t *AST.Type;
|
var t *AST.Type;
|
||||||
if P.expr_lev > 0 {
|
if P.expr_lev >= 0 {
|
||||||
t = ExprType(x);
|
t = ExprType(x);
|
||||||
}
|
}
|
||||||
if t != nil {
|
if t != nil {
|
||||||
@ -1002,7 +1043,7 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat {
|
|||||||
P.Expect(keyword);
|
P.Expect(keyword);
|
||||||
if P.tok != Scanner.LBRACE {
|
if P.tok != Scanner.LBRACE {
|
||||||
prev_lev := P.expr_lev;
|
prev_lev := P.expr_lev;
|
||||||
P.expr_lev = 0;
|
P.expr_lev = -1;
|
||||||
if P.tok != Scanner.SEMICOLON {
|
if P.tok != Scanner.SEMICOLON {
|
||||||
s.init = P.ParseSimpleStat();
|
s.init = P.ParseSimpleStat();
|
||||||
}
|
}
|
||||||
@ -1129,12 +1170,15 @@ func (P *Parser) ParseCommCase() *AST.Stat {
|
|||||||
s := AST.NewStat(P.pos, Scanner.CASE);
|
s := AST.NewStat(P.pos, Scanner.CASE);
|
||||||
if P.tok == Scanner.CASE {
|
if P.tok == Scanner.CASE {
|
||||||
P.Next();
|
P.Next();
|
||||||
P.ParseExpression(1);
|
x := P.ParseExpression(1);
|
||||||
if P.tok == Scanner.ASSIGN || P.tok == Scanner.DEFINE {
|
if P.tok == Scanner.ASSIGN || P.tok == Scanner.DEFINE {
|
||||||
|
pos, tok := P.pos, P.tok;
|
||||||
P.Next();
|
P.Next();
|
||||||
P.Expect(Scanner.ARROW);
|
P.Expect(Scanner.ARROW);
|
||||||
P.ParseExpression(1);
|
y := P.ParseExpression(1);
|
||||||
|
x = AST.NewExpr(pos, tok, x, y);
|
||||||
}
|
}
|
||||||
|
s.expr = x;
|
||||||
} else {
|
} else {
|
||||||
P.Expect(Scanner.DEFAULT);
|
P.Expect(Scanner.DEFAULT);
|
||||||
}
|
}
|
||||||
|
@ -238,9 +238,9 @@ func (P *Printer) Expr1(x *AST.Expr, prec1 int) {
|
|||||||
case Scanner.COMMA:
|
case Scanner.COMMA:
|
||||||
// list
|
// list
|
||||||
// (don't use binary expression printing because of different spacing)
|
// (don't use binary expression printing because of different spacing)
|
||||||
P.Expr1(x.x, Scanner.LowestPrec);
|
P.Expr(x.x);
|
||||||
P.String(x.pos, ", ");
|
P.String(x.pos, ", ");
|
||||||
P.Expr1(x.y, Scanner.LowestPrec);
|
P.Expr(x.y);
|
||||||
|
|
||||||
case Scanner.PERIOD:
|
case Scanner.PERIOD:
|
||||||
// selector or type guard
|
// selector or type guard
|
||||||
@ -265,14 +265,14 @@ func (P *Printer) Expr1(x *AST.Expr, prec1 int) {
|
|||||||
// call
|
// call
|
||||||
P.Expr1(x.x, Scanner.HighestPrec);
|
P.Expr1(x.x, Scanner.HighestPrec);
|
||||||
P.String(x.pos, "(");
|
P.String(x.pos, "(");
|
||||||
P.Expr1(x.y, Scanner.LowestPrec);
|
P.Expr(x.y);
|
||||||
P.String(0, ")");
|
P.String(0, ")");
|
||||||
|
|
||||||
case Scanner.LBRACE:
|
case Scanner.LBRACE:
|
||||||
// composite
|
// composite
|
||||||
P.Type(x.t);
|
P.Type(x.t);
|
||||||
P.String(x.pos, "{");
|
P.String(x.pos, "{");
|
||||||
P.Expr1(x.y, Scanner.LowestPrec);
|
P.Expr(x.y);
|
||||||
P.String(0, "}");
|
P.String(0, "}");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -285,6 +285,7 @@ export type Scanner struct {
|
|||||||
pos int; // current reading position
|
pos int; // current reading position
|
||||||
ch int; // one char look-ahead
|
ch int; // one char look-ahead
|
||||||
chpos int; // position of ch
|
chpos int; // position of ch
|
||||||
|
linepos int; // position of beginning of line
|
||||||
|
|
||||||
// testmode
|
// testmode
|
||||||
testmode bool;
|
testmode bool;
|
||||||
@ -298,8 +299,8 @@ func (S *Scanner) Next() {
|
|||||||
if S.pos < len(S.src) {
|
if S.pos < len(S.src) {
|
||||||
// assume ascii
|
// assume ascii
|
||||||
r, w := int(S.src[S.pos]), 1;
|
r, w := int(S.src[S.pos]), 1;
|
||||||
if r > 0x80 {
|
if r >= 0x80 {
|
||||||
// wasn't ascii
|
// not ascii
|
||||||
r, w = sys.stringtorune(S.src, S.pos);
|
r, w = sys.stringtorune(S.src, S.pos);
|
||||||
}
|
}
|
||||||
S.ch = r;
|
S.ch = r;
|
||||||
@ -430,17 +431,16 @@ func (S *Scanner) LineCol(pos int) (line, col int) {
|
|||||||
|
|
||||||
|
|
||||||
func (S *Scanner) ErrorMsg(pos int, msg string) {
|
func (S *Scanner) ErrorMsg(pos int, msg string) {
|
||||||
print(S.filename);
|
print(S.filename, ":");
|
||||||
if pos >= 0 {
|
if pos >= 0 {
|
||||||
// print position
|
// print position
|
||||||
line, col := S.LineCol(pos);
|
line, col := S.LineCol(pos);
|
||||||
|
print(line, ":");
|
||||||
if S.columns {
|
if S.columns {
|
||||||
print(":", line, ":", col);
|
print(col, ":");
|
||||||
} else {
|
|
||||||
print(":", line);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print(": ", msg, "\n");
|
print(" ", msg, "\n");
|
||||||
|
|
||||||
S.nerrors++;
|
S.nerrors++;
|
||||||
S.errpos = pos;
|
S.errpos = pos;
|
||||||
@ -486,14 +486,15 @@ func (S *Scanner) Open(filename, src string, columns, testmode bool) {
|
|||||||
S.filename = filename;
|
S.filename = filename;
|
||||||
S.nerrors = 0;
|
S.nerrors = 0;
|
||||||
S.errpos = 0;
|
S.errpos = 0;
|
||||||
|
S.columns = columns;
|
||||||
|
|
||||||
S.src = src;
|
S.src = src;
|
||||||
S.pos = 0;
|
S.pos = 0;
|
||||||
S.columns = columns;
|
S.linepos = 0;
|
||||||
|
|
||||||
S.testmode = testmode;
|
S.testmode = testmode;
|
||||||
|
S.ExpectNoErrors(); // S.src must be set
|
||||||
S.ExpectNoErrors(); // after setting S.src
|
S.Next(); // S.ExpectNoErrrors() must be called before
|
||||||
S.Next(); // after S.ExpectNoErrrors()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -535,10 +536,10 @@ func (S *Scanner) ScanComment() string {
|
|||||||
|
|
||||||
if S.ch == '/' {
|
if S.ch == '/' {
|
||||||
// comment
|
// comment
|
||||||
|
S.Next();
|
||||||
for S.ch >= 0 {
|
for S.ch >= 0 {
|
||||||
S.Next();
|
S.Next();
|
||||||
if S.ch == '\n' {
|
if S.ch == '\n' {
|
||||||
S.Next();
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -550,7 +551,6 @@ func (S *Scanner) ScanComment() string {
|
|||||||
ch := S.ch;
|
ch := S.ch;
|
||||||
S.Next();
|
S.Next();
|
||||||
if ch == '*' && S.ch == '/' {
|
if ch == '*' && S.ch == '/' {
|
||||||
S.Next();
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -559,7 +559,9 @@ func (S *Scanner) ScanComment() string {
|
|||||||
S.Error(pos, "comment not terminated");
|
S.Error(pos, "comment not terminated");
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
S.Next();
|
||||||
comment := S.src[pos : S.chpos];
|
comment := S.src[pos : S.chpos];
|
||||||
|
|
||||||
if S.testmode {
|
if S.testmode {
|
||||||
// interpret ERROR and SYNC comments
|
// interpret ERROR and SYNC comments
|
||||||
oldpos := -1;
|
oldpos := -1;
|
||||||
|
@ -21,8 +21,8 @@ count() {
|
|||||||
apply1() {
|
apply1() {
|
||||||
#echo $1 $2
|
#echo $1 $2
|
||||||
case `basename $F` in
|
case `basename $F` in
|
||||||
selftest.go | func3.go ) ;; # skip - these are test cases for syntax errors
|
selftest.go | func3.go | bug014.go | bug029.go | bug032.go | bug050.go | \
|
||||||
newfn.go ) ;; # skip these - cannot parse w/o type information
|
bug068.go | bug088.go | bug083.go | bug106.go ) ;; # skip - files contain syntax errors
|
||||||
* ) $1 $2; count ;;
|
* ) $1 $2; count ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@ -42,6 +42,8 @@ apply() {
|
|||||||
for F in \
|
for F in \
|
||||||
$GOROOT/usr/gri/pretty/*.go \
|
$GOROOT/usr/gri/pretty/*.go \
|
||||||
$GOROOT/test/*.go \
|
$GOROOT/test/*.go \
|
||||||
|
$GOROOT/test/bugs/*.go \
|
||||||
|
$GOROOT/test/fixedbugs/*.go \
|
||||||
$GOROOT/src/pkg/*.go \
|
$GOROOT/src/pkg/*.go \
|
||||||
$GOROOT/src/lib/*.go \
|
$GOROOT/src/lib/*.go \
|
||||||
$GOROOT/src/lib/*/*.go \
|
$GOROOT/src/lib/*/*.go \
|
||||||
|
Loading…
Reference in New Issue
Block a user