diff options
author | Andrew Gerrand <adg@golang.org> | 2011-10-18 14:06:11 +1100 |
---|---|---|
committer | Andrew Gerrand <adg@golang.org> | 2011-10-18 14:06:11 +1100 |
commit | 0584eb2e7779d5bf699702d06acb686cd08bddd2 (patch) | |
tree | 291e3db413833a248a5afbb4cb023e23ca78593e /src/pkg/exp/datafmt/parser.go | |
parent | adfa87c5d754252f2bf428b38560de3d630dbe9d (diff) | |
download | go-git-release-branch.r58.tar.gz |
[release-branch.r58] reflect: disallow Interface method on Value obtained via unexported namerelease.r58.2release-branch.r58
Also remove exp/datafmt that depends on the broken reflect behavior.
««« CL 5267049 / eeca0d4a91a3
reflect: disallow Interface method on Value obtained via unexported name
Had been allowing it for use by fmt, but it is too hard to lock down.
Fix other packages not to depend on it.
R=r, r
CC=golang-dev
https://golang.org/cl/5266054
»»»
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/5297042
Diffstat (limited to 'src/pkg/exp/datafmt/parser.go')
-rw-r--r-- | src/pkg/exp/datafmt/parser.go | 386 |
1 files changed, 0 insertions, 386 deletions
diff --git a/src/pkg/exp/datafmt/parser.go b/src/pkg/exp/datafmt/parser.go deleted file mode 100644 index 7dedb531a5..0000000000 --- a/src/pkg/exp/datafmt/parser.go +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package datafmt - -import ( - "container/vector" - "go/scanner" - "go/token" - "os" - "strconv" - "strings" -) - -// ---------------------------------------------------------------------------- -// Parsing - -type parser struct { - scanner.ErrorVector - scanner scanner.Scanner - file *token.File - pos token.Pos // token position - tok token.Token // one token look-ahead - lit string // token literal - - packs map[string]string // PackageName -> ImportPath - rules map[string]expr // RuleName -> Expression -} - - -func (p *parser) next() { - p.pos, p.tok, p.lit = p.scanner.Scan() - switch p.tok { - case token.CHAN, token.FUNC, token.INTERFACE, token.MAP, token.STRUCT: - // Go keywords for composite types are type names - // returned by reflect. Accept them as identifiers. - p.tok = token.IDENT // p.lit is already set correctly - } -} - - -func (p *parser) init(fset *token.FileSet, filename string, src []byte) { - p.ErrorVector.Reset() - p.file = fset.AddFile(filename, fset.Base(), len(src)) - p.scanner.Init(p.file, src, p, scanner.AllowIllegalChars) // return '@' as token.ILLEGAL w/o error message - p.next() // initializes pos, tok, lit - p.packs = make(map[string]string) - p.rules = make(map[string]expr) -} - - -func (p *parser) error(pos token.Pos, msg string) { - p.Error(p.file.Position(pos), msg) -} - - -func (p *parser) errorExpected(pos token.Pos, msg string) { - msg = "expected " + msg - if pos == p.pos { - // the error happened at the current position; - // make the error message more specific - msg += ", found '" + p.tok.String() + "'" - if p.tok.IsLiteral() { - msg += " " + p.lit - } - } - p.error(pos, msg) -} - - -func (p *parser) expect(tok token.Token) token.Pos { - pos := p.pos - if p.tok != tok { - p.errorExpected(pos, "'"+tok.String()+"'") - } - p.next() // make progress in any case - return pos -} - - -func (p *parser) parseIdentifier() string { - name := p.lit - p.expect(token.IDENT) - return name -} - - -func (p *parser) parseTypeName() (string, bool) { - pos := p.pos - name, isIdent := p.parseIdentifier(), true - if p.tok == token.PERIOD { - // got a package name, lookup package - if importPath, found := p.packs[name]; found { - name = importPath - } else { - p.error(pos, "package not declared: "+name) - } - p.next() - name, isIdent = name+"."+p.parseIdentifier(), false - } - return name, isIdent -} - - -// Parses a rule name and returns it. If the rule name is -// a package-qualified type name, the package name is resolved. -// The 2nd result value is true iff the rule name consists of a -// single identifier only (and thus could be a package name). -// -func (p *parser) parseRuleName() (string, bool) { - name, isIdent := "", false - switch p.tok { - case token.IDENT: - name, isIdent = p.parseTypeName() - case token.DEFAULT: - name = "default" - p.next() - case token.QUO: - name = "/" - p.next() - default: - p.errorExpected(p.pos, "rule name") - p.next() // make progress in any case - } - return name, isIdent -} - - -func (p *parser) parseString() string { - s := "" - if p.tok == token.STRING { - s, _ = strconv.Unquote(p.lit) - // Unquote may fail with an error, but only if the scanner found - // an illegal string in the first place. In this case the error - // has already been reported. - p.next() - return s - } else { - p.expect(token.STRING) - } - return s -} - - -func (p *parser) parseLiteral() literal { - s := []byte(p.parseString()) - - // A string literal may contain %-format specifiers. To simplify - // and speed up printing of the literal, split it into segments - // that start with "%" possibly followed by a last segment that - // starts with some other character. - var list vector.Vector - i0 := 0 - for i := 0; i < len(s); i++ { - if s[i] == '%' && i+1 < len(s) { - // the next segment starts with a % format - if i0 < i { - // the current segment is not empty, split it off - list.Push(s[i0:i]) - i0 = i - } - i++ // skip %; let loop skip over char after % - } - } - // the final segment may start with any character - // (it is empty iff the string is empty) - list.Push(s[i0:]) - - // convert list into a literal - lit := make(literal, list.Len()) - for i := 0; i < list.Len(); i++ { - lit[i] = list.At(i).([]byte) - } - - return lit -} - - -func (p *parser) parseField() expr { - var fname string - switch p.tok { - case token.ILLEGAL: - if p.lit != "@" { - return nil - } - fname = "@" - p.next() - case token.MUL: - fname = "*" - p.next() - case token.IDENT: - fname = p.parseIdentifier() - default: - return nil - } - - var ruleName string - if p.tok == token.COLON { - p.next() - ruleName, _ = p.parseRuleName() - } - - return &field{fname, ruleName} -} - - -func (p *parser) parseOperand() (x expr) { - switch p.tok { - case token.STRING: - x = p.parseLiteral() - - case token.LPAREN: - p.next() - x = p.parseExpression() - if p.tok == token.SHR { - p.next() - x = &group{x, p.parseExpression()} - } - p.expect(token.RPAREN) - - case token.LBRACK: - p.next() - x = &option{p.parseExpression()} - p.expect(token.RBRACK) - - case token.LBRACE: - p.next() - x = p.parseExpression() - var div expr - if p.tok == token.QUO { - p.next() - div = p.parseExpression() - } - x = &repetition{x, div} - p.expect(token.RBRACE) - - default: - x = p.parseField() // may be nil - } - - return x -} - - -func (p *parser) parseSequence() expr { - var list vector.Vector - - for x := p.parseOperand(); x != nil; x = p.parseOperand() { - list.Push(x) - } - - // no need for a sequence if list.Len() < 2 - switch list.Len() { - case 0: - return nil - case 1: - return list.At(0).(expr) - } - - // convert list into a sequence - seq := make(sequence, list.Len()) - for i := 0; i < list.Len(); i++ { - seq[i] = list.At(i).(expr) - } - return seq -} - - -func (p *parser) parseExpression() expr { - var list vector.Vector - - for { - x := p.parseSequence() - if x != nil { - list.Push(x) - } - if p.tok != token.OR { - break - } - p.next() - } - - // no need for an alternatives if list.Len() < 2 - switch list.Len() { - case 0: - return nil - case 1: - return list.At(0).(expr) - } - - // convert list into a alternatives - alt := make(alternatives, list.Len()) - for i := 0; i < list.Len(); i++ { - alt[i] = list.At(i).(expr) - } - return alt -} - - -func (p *parser) parseFormat() { - for p.tok != token.EOF { - pos := p.pos - - name, isIdent := p.parseRuleName() - switch p.tok { - case token.STRING: - // package declaration - importPath := p.parseString() - - // add package declaration - if !isIdent { - p.error(pos, "illegal package name: "+name) - } else if _, found := p.packs[name]; !found { - p.packs[name] = importPath - } else { - p.error(pos, "package already declared: "+name) - } - - case token.ASSIGN: - // format rule - p.next() - x := p.parseExpression() - - // add rule - if _, found := p.rules[name]; !found { - p.rules[name] = x - } else { - p.error(pos, "format rule already declared: "+name) - } - - default: - p.errorExpected(p.pos, "package declaration or format rule") - p.next() // make progress in any case - } - - if p.tok == token.SEMICOLON { - p.next() - } else { - break - } - } - p.expect(token.EOF) -} - - -func remap(p *parser, name string) string { - i := strings.Index(name, ".") - if i >= 0 { - packageName, suffix := name[0:i], name[i:] - // lookup package - if importPath, found := p.packs[packageName]; found { - name = importPath + suffix - } else { - var invalidPos token.Position - p.Error(invalidPos, "package not declared: "+packageName) - } - } - return name -} - - -// Parse parses a set of format productions from source src. Custom -// formatters may be provided via a map of formatter functions. If -// there are no errors, the result is a Format and the error is nil. -// Otherwise the format is nil and a non-empty ErrorList is returned. -// -func Parse(fset *token.FileSet, filename string, src []byte, fmap FormatterMap) (Format, os.Error) { - // parse source - var p parser - p.init(fset, filename, src) - p.parseFormat() - - // add custom formatters, if any - for name, form := range fmap { - name = remap(&p, name) - if _, found := p.rules[name]; !found { - p.rules[name] = &custom{name, form} - } else { - var invalidPos token.Position - p.Error(invalidPos, "formatter already declared: "+name) - } - } - - return p.rules, p.GetError(scanner.NoMultiples) -} |