Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
187c3536
Commit
187c3536
authored
Oct 11, 2011
by
Robert Griesemer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
exp/datafmt: delete per Go 1 plan
R=r, bradfitz CC=golang-dev
https://golang.org/cl/5249055
parent
e58a7780
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
0 additions
and
1421 deletions
+0
-1421
src/pkg/Makefile
src/pkg/Makefile
+0
-1
src/pkg/exp/datafmt/Makefile
src/pkg/exp/datafmt/Makefile
+0
-12
src/pkg/exp/datafmt/datafmt.go
src/pkg/exp/datafmt/datafmt.go
+0
-710
src/pkg/exp/datafmt/datafmt_test.go
src/pkg/exp/datafmt/datafmt_test.go
+0
-330
src/pkg/exp/datafmt/parser.go
src/pkg/exp/datafmt/parser.go
+0
-368
No files found.
src/pkg/Makefile
View file @
187c3536
...
...
@@ -76,7 +76,6 @@ DIRS=\
encoding/hex
\
encoding/pem
\
exec
\
exp/datafmt
\
exp/ebnf
\
exp/ebnflint
\
exp/gui
\
...
...
src/pkg/exp/datafmt/Makefile
deleted
100644 → 0
View file @
e58a7780
# 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.
include
../../../Make.inc
TARG
=
exp/datafmt
GOFILES
=
\
datafmt.go
\
parser.go
\
include
../../../Make.pkg
src/pkg/exp/datafmt/datafmt.go
deleted
100644 → 0
View file @
e58a7780
This diff is collapsed.
Click to expand it.
src/pkg/exp/datafmt/datafmt_test.go
deleted
100644 → 0
View file @
e58a7780
// 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
(
"fmt"
"testing"
"go/token"
)
var
fset
=
token
.
NewFileSet
()
func
parse
(
t
*
testing
.
T
,
form
string
,
fmap
FormatterMap
)
Format
{
f
,
err
:=
Parse
(
fset
,
""
,
[]
byte
(
form
),
fmap
)
if
err
!=
nil
{
t
.
Errorf
(
"Parse(%s): %v"
,
form
,
err
)
return
nil
}
return
f
}
func
verify
(
t
*
testing
.
T
,
f
Format
,
expected
string
,
args
...
interface
{})
{
if
f
==
nil
{
return
// allow other tests to run
}
result
:=
f
.
Sprint
(
args
...
)
if
result
!=
expected
{
t
.
Errorf
(
"result : `%s`
\n
expected: `%s`
\n\n
"
,
result
,
expected
)
}
}
func
formatter
(
s
*
State
,
value
interface
{},
rule_name
string
)
bool
{
switch
rule_name
{
case
"/"
:
fmt
.
Fprintf
(
s
,
"%d %d %d"
,
s
.
Pos
()
.
Line
,
s
.
LinePos
()
.
Column
,
s
.
Pos
()
.
Column
)
return
true
case
"blank"
:
s
.
Write
([]
byte
{
' '
})
return
true
case
"int"
:
if
value
.
(
int
)
&
1
==
0
{
fmt
.
Fprint
(
s
,
"even "
)
}
else
{
fmt
.
Fprint
(
s
,
"odd "
)
}
return
true
case
"nil"
:
return
false
case
"testing.T"
:
s
.
Write
([]
byte
(
"testing.T"
))
return
true
}
panic
(
"unreachable"
)
return
false
}
func
TestCustomFormatters
(
t
*
testing
.
T
)
{
fmap0
:=
FormatterMap
{
"/"
:
formatter
}
fmap1
:=
FormatterMap
{
"int"
:
formatter
,
"blank"
:
formatter
,
"nil"
:
formatter
}
fmap2
:=
FormatterMap
{
"testing.T"
:
formatter
}
f
:=
parse
(
t
,
`int=`
,
fmap0
)
verify
(
t
,
f
,
``
,
1
,
2
,
3
)
f
=
parse
(
t
,
`int="#"`
,
nil
)
verify
(
t
,
f
,
`###`
,
1
,
2
,
3
)
f
=
parse
(
t
,
`int="#";string="%s"`
,
fmap0
)
verify
(
t
,
f
,
"#1 0 1#1 0 7#1 0 13
\n
2 0 0foo2 0 8
\n
"
,
1
,
2
,
3
,
"
\n
"
,
"foo"
,
"
\n
"
)
f
=
parse
(
t
,
``
,
fmap1
)
verify
(
t
,
f
,
`even odd even odd `
,
0
,
1
,
2
,
3
)
f
=
parse
(
t
,
`/ =@:blank; float64="#"`
,
fmap1
)
verify
(
t
,
f
,
`# # #`
,
0.0
,
1.0
,
2.0
)
f
=
parse
(
t
,
`float64=@:nil`
,
fmap1
)
verify
(
t
,
f
,
``
,
0.0
,
1.0
,
2.0
)
f
=
parse
(
t
,
`testing "testing"; ptr=*`
,
fmap2
)
verify
(
t
,
f
,
`testing.T`
,
t
)
// TODO needs more tests
}
// ----------------------------------------------------------------------------
// Formatting of basic and simple composite types
func
check
(
t
*
testing
.
T
,
form
,
expected
string
,
args
...
interface
{})
{
f
:=
parse
(
t
,
form
,
nil
)
if
f
==
nil
{
return
// allow other tests to run
}
result
:=
f
.
Sprint
(
args
...
)
if
result
!=
expected
{
t
.
Errorf
(
"format : %s
\n
result : `%s`
\n
expected: `%s`
\n\n
"
,
form
,
result
,
expected
)
}
}
func
TestBasicTypes
(
t
*
testing
.
T
)
{
check
(
t
,
``
,
``
)
check
(
t
,
`bool=":%v"`
,
`:true:false`
,
true
,
false
)
check
(
t
,
`int="%b %d %o 0x%x"`
,
`101010 42 52 0x2a`
,
42
)
check
(
t
,
`int="%"`
,
`%`
,
42
)
check
(
t
,
`int="%%"`
,
`%`
,
42
)
check
(
t
,
`int="**%%**"`
,
`**%**`
,
42
)
check
(
t
,
`int="%%%%%%"`
,
`%%%`
,
42
)
check
(
t
,
`int="%%%d%%"`
,
`%42%`
,
42
)
const
i
=
-
42
const
is
=
`-42`
check
(
t
,
`int ="%d"`
,
is
,
i
)
check
(
t
,
`int8 ="%d"`
,
is
,
int8
(
i
))
check
(
t
,
`int16="%d"`
,
is
,
int16
(
i
))
check
(
t
,
`int32="%d"`
,
is
,
int32
(
i
))
check
(
t
,
`int64="%d"`
,
is
,
int64
(
i
))
const
u
=
42
const
us
=
`42`
check
(
t
,
`uint ="%d"`
,
us
,
uint
(
u
))
check
(
t
,
`uint8 ="%d"`
,
us
,
uint8
(
u
))
check
(
t
,
`uint16="%d"`
,
us
,
uint16
(
u
))
check
(
t
,
`uint32="%d"`
,
us
,
uint32
(
u
))
check
(
t
,
`uint64="%d"`
,
us
,
uint64
(
u
))
const
f
=
3.141592
const
fs
=
`3.141592`
check
(
t
,
`float64="%g"`
,
fs
,
f
)
check
(
t
,
`float32="%g"`
,
fs
,
float32
(
f
))
check
(
t
,
`float64="%g"`
,
fs
,
float64
(
f
))
}
func
TestArrayTypes
(
t
*
testing
.
T
)
{
var
a0
[
10
]
int
check
(
t
,
`array="array";`
,
`array`
,
a0
)
a1
:=
[
...
]
int
{
1
,
2
,
3
}
check
(
t
,
`array="array";`
,
`array`
,
a1
)
check
(
t
,
`array={*}; int="%d";`
,
`123`
,
a1
)
check
(
t
,
`array={* / ", "}; int="%d";`
,
`1, 2, 3`
,
a1
)
check
(
t
,
`array={* / *}; int="%d";`
,
`12233`
,
a1
)
a2
:=
[]
interface
{}{
42
,
"foo"
,
3.14
}
check
(
t
,
`array={* / ", "}; interface=*; string="bar"; default="%v";`
,
`42, bar, 3.14`
,
a2
)
}
func
TestChanTypes
(
t
*
testing
.
T
)
{
var
c0
chan
int
check
(
t
,
`chan="chan"`
,
`chan`
,
c0
)
c1
:=
make
(
chan
int
)
go
func
()
{
c1
<-
42
}()
check
(
t
,
`chan="chan"`
,
`chan`
,
c1
)
// check(t, `chan=*`, `42`, c1); // reflection support for chans incomplete
}
func
TestFuncTypes
(
t
*
testing
.
T
)
{
var
f0
func
()
int
check
(
t
,
`func="func"`
,
`func`
,
f0
)
f1
:=
func
()
int
{
return
42
}
check
(
t
,
`func="func"`
,
`func`
,
f1
)
// check(t, `func=*`, `42`, f1); // reflection support for funcs incomplete
}
func
TestMapTypes
(
t
*
testing
.
T
)
{
var
m0
map
[
string
]
int
check
(
t
,
`map="map"`
,
`map`
,
m0
)
m1
:=
map
[
string
]
int
{}
check
(
t
,
`map="map"`
,
`map`
,
m1
)
// check(t, `map=*`, ``, m1); // reflection support for maps incomplete
}
func
TestPointerTypes
(
t
*
testing
.
T
)
{
var
p0
*
int
check
(
t
,
`ptr="ptr"`
,
`ptr`
,
p0
)
check
(
t
,
`ptr=*`
,
``
,
p0
)
check
(
t
,
`ptr=*|"nil"`
,
`nil`
,
p0
)
x
:=
99991
p1
:=
&
x
check
(
t
,
`ptr="ptr"`
,
`ptr`
,
p1
)
check
(
t
,
`ptr=*; int="%d"`
,
`99991`
,
p1
)
}
func
TestDefaultRule
(
t
*
testing
.
T
)
{
check
(
t
,
`default="%v"`
,
`42foo3.14`
,
42
,
"foo"
,
3.14
)
check
(
t
,
`default="%v"; int="%x"`
,
`abcdef`
,
10
,
11
,
12
,
13
,
14
,
15
)
check
(
t
,
`default="%v"; int="%x"`
,
`ab**ef`
,
10
,
11
,
"**"
,
14
,
15
)
check
(
t
,
`default="%x"; int=@:default`
,
`abcdef`
,
10
,
11
,
12
,
13
,
14
,
15
)
}
func
TestGlobalSeparatorRule
(
t
*
testing
.
T
)
{
check
(
t
,
`int="%d"; / ="-"`
,
`1-2-3-4`
,
1
,
2
,
3
,
4
)
check
(
t
,
`int="%x%x"; / ="*"`
,
`aa*aa`
,
10
,
10
)
}
// ----------------------------------------------------------------------------
// Formatting of a struct
type
T1
struct
{
a
int
}
const
F1
=
`datafmt "datafmt";`
+
`int = "%d";`
+
`datafmt.T1 = "<" a ">";`
func
TestStruct1
(
t
*
testing
.
T
)
{
check
(
t
,
F1
,
"<42>"
,
T1
{
42
})
}
// ----------------------------------------------------------------------------
// Formatting of a struct with an optional field (ptr)
type
T2
struct
{
s
string
p
*
T1
}
const
F2a
=
F1
+
`string = "%s";`
+
`ptr = *;`
+
`datafmt.T2 = s ["-" p "-"];`
const
F2b
=
F1
+
`string = "%s";`
+
`ptr = *;`
+
`datafmt.T2 = s ("-" p "-" | "empty");`
func
TestStruct2
(
t
*
testing
.
T
)
{
check
(
t
,
F2a
,
"foo"
,
T2
{
"foo"
,
nil
})
check
(
t
,
F2a
,
"bar-<17>-"
,
T2
{
"bar"
,
&
T1
{
17
}})
check
(
t
,
F2b
,
"fooempty"
,
T2
{
"foo"
,
nil
})
}
// ----------------------------------------------------------------------------
// Formatting of a struct with a repetitive field (slice)
type
T3
struct
{
s
string
a
[]
int
}
const
F3a
=
`datafmt "datafmt";`
+
`default = "%v";`
+
`array = *;`
+
`datafmt.T3 = s {" " a a / ","};`
const
F3b
=
`datafmt "datafmt";`
+
`int = "%d";`
+
`string = "%s";`
+
`array = *;`
+
`nil = ;`
+
`empty = *:nil;`
+
`datafmt.T3 = s [a:empty ": " {a / "-"}]`
func
TestStruct3
(
t
*
testing
.
T
)
{
check
(
t
,
F3a
,
"foo"
,
T3
{
"foo"
,
nil
})
check
(
t
,
F3a
,
"foo 00, 11, 22"
,
T3
{
"foo"
,
[]
int
{
0
,
1
,
2
}})
check
(
t
,
F3b
,
"bar"
,
T3
{
"bar"
,
nil
})
check
(
t
,
F3b
,
"bal: 2-3-5"
,
T3
{
"bal"
,
[]
int
{
2
,
3
,
5
}})
}
// ----------------------------------------------------------------------------
// Formatting of a struct with alternative field
type
T4
struct
{
x
*
int
a
[]
int
}
const
F4a
=
`datafmt "datafmt";`
+
`int = "%d";`
+
`ptr = *;`
+
`array = *;`
+
`nil = ;`
+
`empty = *:nil;`
+
`datafmt.T4 = "<" (x:empty x | "-") ">" `
const
F4b
=
`datafmt "datafmt";`
+
`int = "%d";`
+
`ptr = *;`
+
`array = *;`
+
`nil = ;`
+
`empty = *:nil;`
+
`datafmt.T4 = "<" (a:empty {a / ", "} | "-") ">" `
func
TestStruct4
(
t
*
testing
.
T
)
{
x
:=
7
check
(
t
,
F4a
,
"<->"
,
T4
{
nil
,
nil
})
check
(
t
,
F4a
,
"<7>"
,
T4
{
&
x
,
nil
})
check
(
t
,
F4b
,
"<->"
,
T4
{
nil
,
nil
})
check
(
t
,
F4b
,
"<2, 3, 7>"
,
T4
{
nil
,
[]
int
{
2
,
3
,
7
}})
}
// ----------------------------------------------------------------------------
// Formatting a struct (documentation example)
type
Point
struct
{
name
string
x
,
y
int
}
const
FPoint
=
`datafmt "datafmt";`
+
`int = "%d";`
+
`hexInt = "0x%x";`
+
`string = "---%s---";`
+
`datafmt.Point = name "{" x ", " y:hexInt "}";`
func
TestStructPoint
(
t
*
testing
.
T
)
{
p
:=
Point
{
"foo"
,
3
,
15
}
check
(
t
,
FPoint
,
"---foo---{3, 0xf}"
,
p
)
}
// ----------------------------------------------------------------------------
// Formatting a slice (documentation example)
const
FSlice
=
`int = "%b";`
+
`array = { * / ", " }`
func
TestSlice
(
t
*
testing
.
T
)
{
check
(
t
,
FSlice
,
"10, 11, 101, 111"
,
[]
int
{
2
,
3
,
5
,
7
})
}
// TODO add more tests
src/pkg/exp/datafmt/parser.go
deleted
100644 → 0
View file @
e58a7780
// 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
(
"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
[]
interface
{}
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
=
append
(
list
,
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
=
append
(
list
,
s
[
i0
:
])
// convert list into a literal
lit
:=
make
(
literal
,
len
(
list
))
for
i
:=
0
;
i
<
len
(
list
);
i
++
{
lit
[
i
]
=
list
[
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
[]
interface
{}
for
x
:=
p
.
parseOperand
();
x
!=
nil
;
x
=
p
.
parseOperand
()
{
list
=
append
(
list
,
x
)
}
// no need for a sequence if list.Len() < 2
switch
len
(
list
)
{
case
0
:
return
nil
case
1
:
return
list
[
0
]
.
(
expr
)
}
// convert list into a sequence
seq
:=
make
(
sequence
,
len
(
list
))
for
i
:=
0
;
i
<
len
(
list
);
i
++
{
seq
[
i
]
=
list
[
i
]
.
(
expr
)
}
return
seq
}
func
(
p
*
parser
)
parseExpression
()
expr
{
var
list
[]
interface
{}
for
{
x
:=
p
.
parseSequence
()
if
x
!=
nil
{
list
=
append
(
list
,
x
)
}
if
p
.
tok
!=
token
.
OR
{
break
}
p
.
next
()
}
// no need for an alternatives if list.Len() < 2
switch
len
(
list
)
{
case
0
:
return
nil
case
1
:
return
list
[
0
]
.
(
expr
)
}
// convert list into a alternatives
alt
:=
make
(
alternatives
,
len
(
list
))
for
i
:=
0
;
i
<
len
(
list
);
i
++
{
alt
[
i
]
=
list
[
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
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment