summaryrefslogtreecommitdiff
path: root/src/pkg/go/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/go/parser')
-rw-r--r--src/pkg/go/parser/interface.go4
-rw-r--r--src/pkg/go/parser/parser.go93
-rw-r--r--src/pkg/go/parser/parser_test.go35
3 files changed, 83 insertions, 49 deletions
diff --git a/src/pkg/go/parser/interface.go b/src/pkg/go/parser/interface.go
index 84d699a67..6f35b495e 100644
--- a/src/pkg/go/parser/interface.go
+++ b/src/pkg/go/parser/interface.go
@@ -14,7 +14,7 @@ import (
"io"
"io/ioutil"
"os"
- pathutil "path"
+ "path/filepath"
)
@@ -198,7 +198,7 @@ func ParseDir(fset *token.FileSet, path string, filter func(*os.FileInfo) bool,
for i := 0; i < len(list); i++ {
d := &list[i]
if filter == nil || filter(d) {
- filenames[n] = pathutil.Join(path, d.Name)
+ filenames[n] = filepath.Join(path, d.Name)
n++
}
}
diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go
index 2395b8158..7c5843f36 100644
--- a/src/pkg/go/parser/parser.go
+++ b/src/pkg/go/parser/parser.go
@@ -1327,44 +1327,34 @@ func (p *parser) makeExpr(s ast.Stmt) ast.Expr {
}
-func (p *parser) parseControlClause(isForStmt bool) (s1, s2, s3 ast.Stmt) {
- if p.tok != token.LBRACE {
+func (p *parser) parseIfStmt() *ast.IfStmt {
+ if p.trace {
+ defer un(trace(p, "IfStmt"))
+ }
+
+ pos := p.expect(token.IF)
+
+ var s ast.Stmt
+ var x ast.Expr
+ {
prevLev := p.exprLev
p.exprLev = -1
-
- if p.tok != token.SEMICOLON {
- s1 = p.parseSimpleStmt(false)
- }
if p.tok == token.SEMICOLON {
p.next()
- if p.tok != token.LBRACE && p.tok != token.SEMICOLON {
- s2 = p.parseSimpleStmt(false)
- }
- if isForStmt {
- // for statements have a 3rd section
- p.expectSemi()
- if p.tok != token.LBRACE {
- s3 = p.parseSimpleStmt(false)
- }
- }
+ x = p.parseExpr()
} else {
- s1, s2 = nil, s1
+ s = p.parseSimpleStmt(false)
+ if p.tok == token.SEMICOLON {
+ p.next()
+ x = p.parseExpr()
+ } else {
+ x = p.makeExpr(s)
+ s = nil
+ }
}
-
p.exprLev = prevLev
}
- return s1, s2, s3
-}
-
-
-func (p *parser) parseIfStmt() *ast.IfStmt {
- if p.trace {
- defer un(trace(p, "IfStmt"))
- }
-
- pos := p.expect(token.IF)
- s1, s2, _ := p.parseControlClause(false)
body := p.parseBlockStmt()
var else_ ast.Stmt
if p.tok == token.ELSE {
@@ -1374,7 +1364,7 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
p.expectSemi()
}
- return &ast.IfStmt{pos, s1, p.makeExpr(s2), body, else_}
+ return &ast.IfStmt{pos, s, x, body, else_}
}
@@ -1457,7 +1447,24 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
}
pos := p.expect(token.SWITCH)
- s1, s2, _ := p.parseControlClause(false)
+
+ var s1, s2 ast.Stmt
+ if p.tok != token.LBRACE {
+ prevLev := p.exprLev
+ p.exprLev = -1
+ if p.tok != token.SEMICOLON {
+ s2 = p.parseSimpleStmt(false)
+ }
+ if p.tok == token.SEMICOLON {
+ p.next()
+ s1 = s2
+ s2 = nil
+ if p.tok != token.LBRACE {
+ s2 = p.parseSimpleStmt(false)
+ }
+ }
+ p.exprLev = prevLev
+ }
if isExprSwitch(s2) {
lbrace := p.expect(token.LBRACE)
@@ -1575,7 +1582,29 @@ func (p *parser) parseForStmt() ast.Stmt {
}
pos := p.expect(token.FOR)
- s1, s2, s3 := p.parseControlClause(true)
+
+ var s1, s2, s3 ast.Stmt
+ if p.tok != token.LBRACE {
+ prevLev := p.exprLev
+ p.exprLev = -1
+ if p.tok != token.SEMICOLON {
+ s2 = p.parseSimpleStmt(false)
+ }
+ if p.tok == token.SEMICOLON {
+ p.next()
+ s1 = s2
+ s2 = nil
+ if p.tok != token.SEMICOLON {
+ s2 = p.parseSimpleStmt(false)
+ }
+ p.expectSemi()
+ if p.tok != token.LBRACE {
+ s3 = p.parseSimpleStmt(false)
+ }
+ }
+ p.exprLev = prevLev
+ }
+
body := p.parseBlockStmt()
p.expectSemi()
diff --git a/src/pkg/go/parser/parser_test.go b/src/pkg/go/parser/parser_test.go
index 5a7f05ca8..38535627a 100644
--- a/src/pkg/go/parser/parser_test.go
+++ b/src/pkg/go/parser/parser_test.go
@@ -18,6 +18,9 @@ var illegalInputs = []interface{}{
3.14,
[]byte(nil),
"foo!",
+ `package p; func f() { if /* should have condition */ {} };`,
+ `package p; func f() { if ; /* should have condition */ {} };`,
+ `package p; func f() { if f(); /* should have condition */ {} };`,
}
@@ -32,21 +35,23 @@ func TestParseIllegalInputs(t *testing.T) {
var validPrograms = []interface{}{
- "package main\n",
- `package main;`,
- `package main; import "fmt"; func main() { fmt.Println("Hello, World!") };`,
- `package main; func main() { if f(T{}) {} };`,
- `package main; func main() { _ = (<-chan int)(x) };`,
- `package main; func main() { _ = (<-chan <-chan int)(x) };`,
- `package main; func f(func() func() func());`,
- `package main; func f(...T);`,
- `package main; func f(float, ...int);`,
- `package main; func f(x int, a ...int) { f(0, a...); f(1, a...,) };`,
- `package main; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`,
- `package main; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`,
- `package main; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`,
- `package main; var a = T{{1, 2}, {3, 4}}`,
- `package main; func f() { select { case <- c: case c <- d: case c <- <- d: case <-c <- d: } };`,
+ "package p\n",
+ `package p;`,
+ `package p; import "fmt"; func f() { fmt.Println("Hello, World!") };`,
+ `package p; func f() { if f(T{}) {} };`,
+ `package p; func f() { _ = (<-chan int)(x) };`,
+ `package p; func f() { _ = (<-chan <-chan int)(x) };`,
+ `package p; func f(func() func() func());`,
+ `package p; func f(...T);`,
+ `package p; func f(float, ...int);`,
+ `package p; func f(x int, a ...int) { f(0, a...); f(1, a...,) };`,
+ `package p; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`,
+ `package p; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`,
+ `package p; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`,
+ `package p; var a = T{{1, 2}, {3, 4}}`,
+ `package p; func f() { select { case <- c: case c <- d: case c <- <- d: case <-c <- d: } };`,
+ `package p; func f() { if ; true {} };`,
+ `package p; func f() { switch ; {} };`,
}