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
2527bba9
Commit
2527bba9
authored
Jan 15, 2009
by
Robert Griesemer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
casify pretty
R=r OCL=22899 CL=22899
parent
605d0746
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
620 additions
and
618 deletions
+620
-618
usr/gri/pretty/ast.go
usr/gri/pretty/ast.go
+76
-76
usr/gri/pretty/compilation.go
usr/gri/pretty/compilation.go
+17
-17
usr/gri/pretty/parser.go
usr/gri/pretty/parser.go
+163
-163
usr/gri/pretty/platform.go
usr/gri/pretty/platform.go
+10
-10
usr/gri/pretty/pretty.go
usr/gri/pretty/pretty.go
+2
-2
usr/gri/pretty/printer.go
usr/gri/pretty/printer.go
+148
-148
usr/gri/pretty/scanner.go
usr/gri/pretty/scanner.go
+106
-105
usr/gri/pretty/selftest0.go
usr/gri/pretty/selftest0.go
+1
-1
usr/gri/pretty/selftest2.go
usr/gri/pretty/selftest2.go
+9
-9
usr/gri/pretty/test.sh
usr/gri/pretty/test.sh
+3
-2
usr/gri/pretty/typechecker.go
usr/gri/pretty/typechecker.go
+13
-13
usr/gri/pretty/universe.go
usr/gri/pretty/universe.go
+72
-72
No files found.
usr/gri/pretty/ast.go
View file @
2527bba9
...
...
@@ -54,23 +54,23 @@ export func KindStr(kind int) string {
export
type
Object
struct
{
i
d
int
;
// unique id
I
d
int
;
// unique id
p
os
int
;
// source position (< 0 if unknown position)
k
ind
int
;
// object kind
i
dent
string
;
t
yp
*
Type
;
// nil for packages
p
nolev
int
;
// >= 0: package no., <= 0: function nesting level, 0: global level
P
os
int
;
// source position (< 0 if unknown position)
K
ind
int
;
// object kind
I
dent
string
;
T
yp
*
Type
;
// nil for packages
P
nolev
int
;
// >= 0: package no., <= 0: function nesting level, 0: global level
// attached values
block
*
array
.
Array
;
e
nd
int
;
// stats for function literals; end of block pos
Block
*
array
.
Array
;
E
nd
int
;
// stats for function literals; end of block pos
}
func
(
obj
*
Object
)
IsExported
()
bool
{
switch
obj
.
k
ind
{
switch
obj
.
K
ind
{
case
NONE
/* FUNC for now */
,
CONST
,
TYPE
,
VAR
,
FUNC
:
ch
,
size
:=
utf8
.
DecodeRuneInString
(
obj
.
i
dent
,
0
);
ch
,
size
:=
utf8
.
DecodeRuneInString
(
obj
.
I
dent
,
0
);
return
unicode
.
IsUpper
(
ch
);
}
return
false
;
...
...
@@ -78,18 +78,18 @@ func (obj *Object) IsExported() bool {
export
var
Universe_void_typ
*
Type
// initialized by Universe to Universe.void_typ
var
O
bjectId
int
;
var
o
bjectId
int
;
export
func
NewObject
(
pos
,
kind
int
,
ident
string
)
*
Object
{
obj
:=
new
(
Object
);
obj
.
id
=
O
bjectId
;
O
bjectId
++
;
obj
.
Id
=
o
bjectId
;
o
bjectId
++
;
obj
.
p
os
=
pos
;
obj
.
k
ind
=
kind
;
obj
.
i
dent
=
ident
;
obj
.
t
yp
=
Universe_void_typ
;
obj
.
p
nolev
=
0
;
obj
.
P
os
=
pos
;
obj
.
K
ind
=
kind
;
obj
.
I
dent
=
ident
;
obj
.
T
yp
=
Universe_void_typ
;
obj
.
P
nolev
=
0
;
return
obj
;
}
...
...
@@ -133,23 +133,23 @@ func (scope *Scope) Lookup(ident string) *Object {
}
func
(
scope
*
Scope
)
A
dd
(
obj
*
Object
)
{
scope
.
entries
[
obj
.
i
dent
]
=
obj
;
func
(
scope
*
Scope
)
a
dd
(
obj
*
Object
)
{
scope
.
entries
[
obj
.
I
dent
]
=
obj
;
}
func
(
scope
*
Scope
)
Insert
(
obj
*
Object
)
{
if
scope
.
LookupLocal
(
obj
.
i
dent
)
!=
nil
{
if
scope
.
LookupLocal
(
obj
.
I
dent
)
!=
nil
{
panic
(
"obj already inserted"
);
}
scope
.
A
dd
(
obj
);
scope
.
a
dd
(
obj
);
}
func
(
scope
*
Scope
)
InsertImport
(
obj
*
Object
)
*
Object
{
p
:=
scope
.
LookupLocal
(
obj
.
i
dent
);
p
:=
scope
.
LookupLocal
(
obj
.
I
dent
);
if
p
==
nil
{
scope
.
A
dd
(
obj
);
scope
.
a
dd
(
obj
);
p
=
obj
;
}
return
p
;
...
...
@@ -169,8 +169,8 @@ func (scope *Scope) Print() {
// All nodes have a source position and and token.
export
type
Node
struct
{
p
os
int
;
// source position (< 0 => unknown position)
t
ok
int
;
// identifying token
P
os
int
;
// source position (< 0 => unknown position)
T
ok
int
;
// identifying token
}
...
...
@@ -179,8 +179,8 @@ export type Node struct {
export
type
Expr
struct
{
Node
;
x
,
y
*
Expr
;
// binary (x, y) and unary (y
) expressions
o
bj
*
Object
;
X
,
Y
*
Expr
;
// binary (X, Y) and unary (Y
) expressions
O
bj
*
Object
;
}
...
...
@@ -189,7 +189,7 @@ func (x *Expr) Len() int {
return
0
;
}
n
:=
1
;
for
;
x
.
tok
==
Scanner
.
COMMA
;
x
=
x
.
y
{
for
;
x
.
Tok
==
Scanner
.
COMMA
;
x
=
x
.
Y
{
n
++
;
}
return
n
;
...
...
@@ -197,11 +197,11 @@ func (x *Expr) Len() int {
export
func
NewExpr
(
pos
,
tok
int
,
x
,
y
*
Expr
)
*
Expr
{
if
x
!=
nil
&&
x
.
tok
==
Scanner
.
TYPE
||
y
!=
nil
&&
y
.
t
ok
==
Scanner
.
TYPE
{
if
x
!=
nil
&&
x
.
Tok
==
Scanner
.
TYPE
||
y
!=
nil
&&
y
.
T
ok
==
Scanner
.
TYPE
{
panic
(
"no type expression allowed"
);
}
e
:=
new
(
Expr
);
e
.
pos
,
e
.
tok
,
e
.
x
,
e
.
y
=
pos
,
tok
,
x
,
y
;
e
.
Pos
,
e
.
Tok
,
e
.
X
,
e
.
Y
=
pos
,
tok
,
x
,
y
;
return
e
;
}
...
...
@@ -209,7 +209,7 @@ export func NewExpr(pos, tok int, x, y *Expr) *Expr {
// TODO probably don't need the tok parameter eventually
export
func
NewLit
(
tok
int
,
obj
*
Object
)
*
Expr
{
e
:=
new
(
Expr
);
e
.
pos
,
e
.
tok
,
e
.
obj
=
obj
.
p
os
,
tok
,
obj
;
e
.
Pos
,
e
.
Tok
,
e
.
Obj
=
obj
.
P
os
,
tok
,
obj
;
return
e
;
}
...
...
@@ -296,47 +296,47 @@ export const /* channel mode */ (
export
type
Type
struct
{
i
d
int
;
// unique id
I
d
int
;
// unique id
r
ef
int
;
// for exporting only: >= 0 means already exported
f
orm
int
;
// type form
s
ize
int
;
// size in bytes
o
bj
*
Object
;
// primary type object or NULL
s
cope
*
Scope
;
// forwards, structs, interfaces, functions
R
ef
int
;
// for exporting only: >= 0 means already exported
F
orm
int
;
// type form
S
ize
int
;
// size in bytes
O
bj
*
Object
;
// primary type object or NULL
S
cope
*
Scope
;
// forwards, structs, interfaces, functions
// syntactic components
p
os
int
;
// source position (< 0 if unknown position)
e
xpr
*
Expr
;
// type name, array length
m
ode
int
;
// channel mode
k
ey
*
Type
;
// receiver type or map key
e
lt
*
Type
;
// array, map, channel or pointer element type, function result type
list
*
array
.
Array
;
e
nd
int
;
// struct fields, interface methods, function parameters
s
cope
*
Scope
;
// struct fields, methods
P
os
int
;
// source position (< 0 if unknown position)
E
xpr
*
Expr
;
// type name, array length
M
ode
int
;
// channel mode
K
ey
*
Type
;
// receiver type or map key
E
lt
*
Type
;
// array, map, channel or pointer element type, function result type
List
*
array
.
Array
;
E
nd
int
;
// struct fields, interface methods, function parameters
S
cope
*
Scope
;
// struct fields, methods
}
var
T
ypeId
int
;
var
t
ypeId
int
;
export
func
NewType
(
pos
,
form
int
)
*
Type
{
typ
:=
new
(
Type
);
typ
.
id
=
T
ypeId
;
T
ypeId
++
;
typ
.
Id
=
t
ypeId
;
t
ypeId
++
;
typ
.
r
ef
=
-
1
;
// not yet exported
typ
.
p
os
=
pos
;
typ
.
f
orm
=
form
;
typ
.
R
ef
=
-
1
;
// not yet exported
typ
.
P
os
=
pos
;
typ
.
F
orm
=
form
;
return
typ
;
}
func
(
t
*
Type
)
n
fields
()
int
{
if
t
.
l
ist
==
nil
{
func
(
t
*
Type
)
N
fields
()
int
{
if
t
.
L
ist
==
nil
{
return
0
;
}
nx
,
nt
:=
0
,
0
;
for
i
,
n
:=
0
,
t
.
l
ist
.
Len
();
i
<
n
;
i
++
{
if
t
.
list
.
At
(
i
)
.
(
*
Expr
)
.
t
ok
==
Scanner
.
TYPE
{
for
i
,
n
:=
0
,
t
.
L
ist
.
Len
();
i
<
n
;
i
++
{
if
t
.
List
.
At
(
i
)
.
(
*
Expr
)
.
T
ok
==
Scanner
.
TYPE
{
nt
++
;
}
else
{
nx
++
;
...
...
@@ -349,10 +349,10 @@ func (t *Type) nfields() int {
}
// requires complete Type.
p
os access
// requires complete Type.
P
os access
export
func
NewTypeExpr
(
typ
*
Type
)
*
Expr
{
obj
:=
NewObject
(
typ
.
p
os
,
TYPE
,
""
);
obj
.
t
yp
=
typ
;
obj
:=
NewObject
(
typ
.
P
os
,
TYPE
,
""
);
obj
.
T
yp
=
typ
;
return
NewLit
(
Scanner
.
TYPE
,
obj
);
}
...
...
@@ -365,16 +365,16 @@ export var BadType = NewType(0, Scanner.ILLEGAL);
export
type
Stat
struct
{
Node
;
init
,
p
ost
*
Stat
;
e
xpr
*
Expr
;
block
*
array
.
Array
;
e
nd
int
;
// block end position
d
ecl
*
Decl
;
Init
,
P
ost
*
Stat
;
E
xpr
*
Expr
;
Block
*
array
.
Array
;
E
nd
int
;
// block end position
D
ecl
*
Decl
;
}
export
func
NewStat
(
pos
,
tok
int
)
*
Stat
{
s
:=
new
(
Stat
);
s
.
pos
,
s
.
t
ok
=
pos
,
tok
;
s
.
Pos
,
s
.
T
ok
=
pos
,
tok
;
return
s
;
}
...
...
@@ -387,19 +387,19 @@ export var BadStat = NewStat(0, Scanner.ILLEGAL);
export
type
Decl
struct
{
Node
;
e
xported
bool
;
i
dent
*
Expr
;
// nil for ()-style declarations
t
yp
*
Type
;
v
al
*
Expr
;
E
xported
bool
;
I
dent
*
Expr
;
// nil for ()-style declarations
T
yp
*
Type
;
V
al
*
Expr
;
// list of *Decl for ()-style declarations
// list of *Stat for func declarations (or nil for forward decl)
list
*
array
.
Array
;
e
nd
int
;
List
*
array
.
Array
;
E
nd
int
;
}
export
func
NewDecl
(
pos
,
tok
int
,
exported
bool
)
*
Decl
{
d
:=
new
(
Decl
);
d
.
pos
,
d
.
tok
,
d
.
e
xported
=
pos
,
tok
,
exported
;
d
.
Pos
,
d
.
Tok
,
d
.
E
xported
=
pos
,
tok
,
exported
;
return
d
;
}
...
...
@@ -411,28 +411,28 @@ export var BadDecl = NewDecl(0, Scanner.ILLEGAL, false);
// Program
export
type
Comment
struct
{
p
os
int
;
t
ext
string
;
P
os
int
;
T
ext
string
;
}
export
func
NewComment
(
pos
int
,
text
string
)
*
Comment
{
c
:=
new
(
Comment
);
c
.
pos
,
c
.
t
ext
=
pos
,
text
;
c
.
Pos
,
c
.
T
ext
=
pos
,
text
;
return
c
;
}
export
type
Program
struct
{
p
os
int
;
// tok is Scanner.PACKAGE
i
dent
*
Expr
;
d
ecls
*
array
.
Array
;
c
omments
*
array
.
Array
;
P
os
int
;
// tok is Scanner.PACKAGE
I
dent
*
Expr
;
D
ecls
*
array
.
Array
;
C
omments
*
array
.
Array
;
}
export
func
NewProgram
(
pos
int
)
*
Program
{
p
:=
new
(
Program
);
p
.
p
os
=
pos
;
p
.
P
os
=
pos
;
return
p
;
}
usr/gri/pretty/compilation.go
View file @
2527bba9
...
...
@@ -34,7 +34,7 @@ export type Flags struct {
}
type
E
rrorHandler
struct
{
type
e
rrorHandler
struct
{
filename
string
;
src
string
;
nerrors
int
;
...
...
@@ -44,7 +44,7 @@ type ErrorHandler struct {
}
func
(
h
*
E
rrorHandler
)
Init
(
filename
,
src
string
,
columns
bool
)
{
func
(
h
*
e
rrorHandler
)
Init
(
filename
,
src
string
,
columns
bool
)
{
h
.
filename
=
filename
;
h
.
src
=
src
;
h
.
nerrors
=
0
;
...
...
@@ -55,7 +55,7 @@ func (h *ErrorHandler) Init(filename, src string, columns bool) {
// Compute (line, column) information for a given source position.
func
(
h
*
E
rrorHandler
)
LineCol
(
pos
int
)
(
line
,
col
int
)
{
func
(
h
*
e
rrorHandler
)
LineCol
(
pos
int
)
(
line
,
col
int
)
{
line
=
1
;
lpos
:=
0
;
...
...
@@ -75,7 +75,7 @@ func (h *ErrorHandler) LineCol(pos int) (line, col int) {
}
func
(
h
*
E
rrorHandler
)
ErrorMsg
(
pos
int
,
msg
string
)
{
func
(
h
*
e
rrorHandler
)
ErrorMsg
(
pos
int
,
msg
string
)
{
print
(
h
.
filename
,
":"
);
if
pos
>=
0
{
// print position
...
...
@@ -97,7 +97,7 @@ func (h *ErrorHandler) ErrorMsg(pos int, msg string) {
}
func
(
h
*
E
rrorHandler
)
Error
(
pos
int
,
msg
string
)
{
func
(
h
*
e
rrorHandler
)
Error
(
pos
int
,
msg
string
)
{
// only report errors that are sufficiently far away from the previous error
// in the hope to avoid most follow-up errors
const
errdist
=
20
;
...
...
@@ -112,7 +112,7 @@ func (h *ErrorHandler) Error(pos int, msg string) {
}
func
(
h
*
E
rrorHandler
)
Warning
(
pos
int
,
msg
string
)
{
func
(
h
*
e
rrorHandler
)
Warning
(
pos
int
,
msg
string
)
{
panic
(
"UNIMPLEMENTED"
);
}
...
...
@@ -124,7 +124,7 @@ export func Compile(src_file string, flags *Flags) (*AST.Program, int) {
return
nil
,
1
;
}
var
err
E
rrorHandler
;
var
err
e
rrorHandler
;
err
.
Init
(
src_file
,
src
,
flags
.
columns
);
var
scanner
Scanner
.
Scanner
;
...
...
@@ -148,7 +148,7 @@ export func Compile(src_file string, flags *Flags) (*AST.Program, int) {
}
func
F
ileExists
(
name
string
)
bool
{
func
f
ileExists
(
name
string
)
bool
{
fd
,
err
:=
OS
.
Open
(
name
,
OS
.
O_RDONLY
,
0
);
if
err
==
nil
{
fd
.
Close
();
...
...
@@ -158,7 +158,7 @@ func FileExists(name string) bool {
}
func
A
ddDeps
(
globalset
map
[
string
]
bool
,
wset
*
array
.
Array
,
src_file
string
,
flags
*
Flags
)
{
func
a
ddDeps
(
globalset
map
[
string
]
bool
,
wset
*
array
.
Array
,
src_file
string
,
flags
*
Flags
)
{
dummy
,
found
:=
globalset
[
src_file
];
if
!
found
{
globalset
[
src_file
]
=
true
;
...
...
@@ -168,27 +168,27 @@ func AddDeps(globalset map [string] bool, wset *array.Array, src_file string, fl
return
;
}
nimports
:=
prog
.
d
ecls
.
Len
();
nimports
:=
prog
.
D
ecls
.
Len
();
if
nimports
>
0
{
print
(
src_file
,
".6:
\t
"
);
localset
:=
make
(
map
[
string
]
bool
);
for
i
:=
0
;
i
<
nimports
;
i
++
{
decl
:=
prog
.
d
ecls
.
At
(
i
)
.
(
*
AST
.
Decl
);
assert
(
decl
.
tok
==
Scanner
.
IMPORT
&&
decl
.
val
.
t
ok
==
Scanner
.
STRING
);
src
:=
decl
.
val
.
obj
.
i
dent
;
decl
:=
prog
.
D
ecls
.
At
(
i
)
.
(
*
AST
.
Decl
);
assert
(
decl
.
Tok
==
Scanner
.
IMPORT
&&
decl
.
Val
.
T
ok
==
Scanner
.
STRING
);
src
:=
decl
.
Val
.
Obj
.
I
dent
;
src
=
src
[
1
:
len
(
src
)
-
1
];
// strip "'s
// ignore files when they are seen a 2nd time
dummy
,
found
:=
localset
[
src
];
if
!
found
{
localset
[
src
]
=
true
;
if
F
ileExists
(
src
+
".go"
)
{
if
f
ileExists
(
src
+
".go"
)
{
wset
.
Push
(
src
);
print
(
" "
,
src
,
".6"
);
}
else
if
F
ileExists
(
Platform
.
GOROOT
+
"/pkg/"
+
src
+
".6"
)
||
F
ileExists
(
Platform
.
GOROOT
+
"/pkg/"
+
src
+
".a"
)
{
f
ileExists
(
Platform
.
GOROOT
+
"/pkg/"
+
src
+
".6"
)
||
f
ileExists
(
Platform
.
GOROOT
+
"/pkg/"
+
src
+
".a"
)
{
}
else
{
// TODO should collect these and print later
...
...
@@ -207,6 +207,6 @@ export func ComputeDeps(src_file string, flags *Flags) {
wset
:=
array
.
New
(
0
);
wset
.
Push
(
src_file
);
for
wset
.
Len
()
>
0
{
A
ddDeps
(
globalset
,
wset
,
wset
.
Pop
()
.
(
string
),
flags
);
a
ddDeps
(
globalset
,
wset
,
wset
.
Pop
()
.
(
string
),
flags
);
}
}
usr/gri/pretty/parser.go
View file @
2527bba9
...
...
@@ -91,7 +91,7 @@ func (P *Parser) Next0() {
P
.
pos
,
P
.
tok
,
P
.
val
=
P
.
scanner
.
Scan
();
}
else
{
t
:=
<-
P
.
tokchan
;
P
.
tok
,
P
.
pos
,
P
.
val
=
t
.
tok
,
t
.
pos
,
t
.
v
al
;
P
.
tok
,
P
.
pos
,
P
.
val
=
t
.
Tok
,
t
.
Pos
,
t
.
V
al
;
}
P
.
opt_semi
=
false
;
...
...
@@ -168,13 +168,13 @@ func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int) {
if
P
.
scope_lev
<
0
{
panic
(
"cannot declare objects in other packages"
);
}
if
x
.
t
ok
!=
Scanner
.
ILLEGAL
{
// ignore bad exprs
obj
:=
x
.
o
bj
;
assert
(
x
.
tok
==
Scanner
.
IDENT
&&
obj
.
k
ind
==
AST
.
NONE
);
obj
.
k
ind
=
kind
;
obj
.
p
nolev
=
P
.
scope_lev
;
if
scope
.
LookupLocal
(
obj
.
i
dent
)
!=
nil
{
P
.
Error
(
obj
.
pos
,
`"`
+
obj
.
i
dent
+
`" is declared already`
);
if
x
.
T
ok
!=
Scanner
.
ILLEGAL
{
// ignore bad exprs
obj
:=
x
.
O
bj
;
assert
(
x
.
Tok
==
Scanner
.
IDENT
&&
obj
.
K
ind
==
AST
.
NONE
);
obj
.
K
ind
=
kind
;
obj
.
P
nolev
=
P
.
scope_lev
;
if
scope
.
LookupLocal
(
obj
.
I
dent
)
!=
nil
{
P
.
Error
(
obj
.
Pos
,
`"`
+
obj
.
I
dent
+
`" is declared already`
);
return
;
// don't insert it into the scope
}
scope
.
Insert
(
obj
);
...
...
@@ -184,23 +184,23 @@ func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int) {
// Declare a comma-separated list of idents or a single ident.
func
(
P
*
Parser
)
Declare
(
p
*
AST
.
Expr
,
kind
int
)
{
for
p
.
t
ok
==
Scanner
.
COMMA
{
P
.
DeclareInScope
(
P
.
top_scope
,
p
.
x
,
kind
);
p
=
p
.
y
;
for
p
.
T
ok
==
Scanner
.
COMMA
{
P
.
DeclareInScope
(
P
.
top_scope
,
p
.
X
,
kind
);
p
=
p
.
Y
;
}
P
.
DeclareInScope
(
P
.
top_scope
,
p
,
kind
);
}
func
(
P
*
Parser
)
VerifyExport1
(
p
*
AST
.
Expr
,
exported
bool
)
{
obj
:=
p
.
o
bj
;
obj
:=
p
.
O
bj
;
if
exported
{
if
!
obj
.
IsExported
()
{
P
.
Error
(
obj
.
pos
,
`"`
+
obj
.
i
dent
+
`" should be uppercase`
);
P
.
Error
(
obj
.
Pos
,
`"`
+
obj
.
I
dent
+
`" should be uppercase`
);
}
}
else
if
P
.
scope_lev
==
0
{
if
obj
.
IsExported
()
{
P
.
Error
(
obj
.
pos
,
`"`
+
obj
.
i
dent
+
`" should be lowercase`
);
P
.
Error
(
obj
.
Pos
,
`"`
+
obj
.
I
dent
+
`" should be lowercase`
);
}
}
}
...
...
@@ -210,9 +210,9 @@ func (P *Parser) VerifyExport(p *AST.Expr, exported bool) {
if
!
P
.
naming
{
return
;
}
for
p
.
t
ok
==
Scanner
.
COMMA
{
P
.
VerifyExport1
(
p
.
x
,
exported
);
p
=
p
.
y
;
for
p
.
T
ok
==
Scanner
.
COMMA
{
P
.
VerifyExport1
(
p
.
X
,
exported
);
p
=
p
.
Y
;
}
P
.
VerifyExport1
(
p
,
exported
);
}
...
...
@@ -222,27 +222,27 @@ func (P *Parser) VerifyExport(p *AST.Expr, exported bool) {
// ----------------------------------------------------------------------------
// AST support
func
E
xprType
(
x
*
AST
.
Expr
)
*
AST
.
Type
{
func
e
xprType
(
x
*
AST
.
Expr
)
*
AST
.
Type
{
var
t
*
AST
.
Type
;
if
x
.
t
ok
==
Scanner
.
TYPE
{
t
=
x
.
obj
.
t
yp
;
}
else
if
x
.
t
ok
==
Scanner
.
IDENT
{
if
x
.
T
ok
==
Scanner
.
TYPE
{
t
=
x
.
Obj
.
T
yp
;
}
else
if
x
.
T
ok
==
Scanner
.
IDENT
{
// assume a type name
t
=
AST
.
NewType
(
x
.
p
os
,
AST
.
TYPENAME
);
t
.
e
xpr
=
x
;
}
else
if
x
.
tok
==
Scanner
.
PERIOD
&&
x
.
y
!=
nil
&&
ExprType
(
x
.
x
)
!=
nil
{
t
=
AST
.
NewType
(
x
.
P
os
,
AST
.
TYPENAME
);
t
.
E
xpr
=
x
;
}
else
if
x
.
Tok
==
Scanner
.
PERIOD
&&
x
.
Y
!=
nil
&&
exprType
(
x
.
X
)
!=
nil
{
// possibly a qualified (type) identifier
t
=
AST
.
NewType
(
x
.
p
os
,
AST
.
TYPENAME
);
t
.
e
xpr
=
x
;
t
=
AST
.
NewType
(
x
.
P
os
,
AST
.
TYPENAME
);
t
.
E
xpr
=
x
;
}
return
t
;
}
func
(
P
*
Parser
)
NoType
(
x
*
AST
.
Expr
)
*
AST
.
Expr
{
if
x
!=
nil
&&
x
.
t
ok
==
Scanner
.
TYPE
{
P
.
Error
(
x
.
p
os
,
"expected expression, found type"
);
val
:=
AST
.
NewObject
(
x
.
p
os
,
AST
.
NONE
,
"0"
);
if
x
!=
nil
&&
x
.
T
ok
==
Scanner
.
TYPE
{
P
.
Error
(
x
.
P
os
,
"expected expression, found type"
);
val
:=
AST
.
NewObject
(
x
.
P
os
,
AST
.
NONE
,
"0"
);
x
=
AST
.
NewLit
(
Scanner
.
INT
,
val
);
}
return
x
;
...
...
@@ -276,10 +276,10 @@ func (P *Parser) ParseIdent(scope *AST.Scope) *AST.Expr {
if
obj
==
nil
{
obj
=
AST
.
NewObject
(
P
.
pos
,
AST
.
NONE
,
P
.
val
);
}
else
{
assert
(
obj
.
k
ind
!=
AST
.
NONE
);
assert
(
obj
.
K
ind
!=
AST
.
NONE
);
}
x
=
AST
.
NewLit
(
Scanner
.
IDENT
,
obj
);
x
.
p
os
=
P
.
pos
;
// override obj.pos (incorrect if object was looked up!)
x
.
P
os
=
P
.
pos
;
// override obj.pos (incorrect if object was looked up!)
if
P
.
verbose
{
P
.
PrintIndent
();
print
(
"Ident =
\"
"
,
P
.
val
,
"
\"\n
"
);
...
...
@@ -307,8 +307,8 @@ func (P *Parser) ParseIdentList() *AST.Expr {
x
=
P
.
NewExpr
(
pos
,
Scanner
.
COMMA
,
x
,
y
);
last
=
x
;
}
else
{
last
.
y
=
P
.
NewExpr
(
pos
,
Scanner
.
COMMA
,
last
.
y
,
y
);
last
=
last
.
y
;
last
.
Y
=
P
.
NewExpr
(
pos
,
Scanner
.
COMMA
,
last
.
Y
,
y
);
last
=
last
.
Y
;
}
}
...
...
@@ -364,7 +364,7 @@ func (P *Parser) ParseTypeName() *AST.Type {
P
.
Trace
(
"TypeName"
);
t
:=
AST
.
NewType
(
P
.
pos
,
AST
.
TYPENAME
);
t
.
e
xpr
=
P
.
ParseQualifiedIdent
();
t
.
E
xpr
=
P
.
ParseQualifiedIdent
();
P
.
Ecart
();
return
t
;
...
...
@@ -377,13 +377,13 @@ func (P *Parser) ParseArrayType() *AST.Type {
t
:=
AST
.
NewType
(
P
.
pos
,
AST
.
ARRAY
);
P
.
Expect
(
Scanner
.
LBRACK
);
if
P
.
tok
==
Scanner
.
ELLIPSIS
{
t
.
e
xpr
=
P
.
NewExpr
(
P
.
pos
,
Scanner
.
ELLIPSIS
,
nil
,
nil
);
t
.
E
xpr
=
P
.
NewExpr
(
P
.
pos
,
Scanner
.
ELLIPSIS
,
nil
,
nil
);
P
.
Next
();
}
else
if
P
.
tok
!=
Scanner
.
RBRACK
{
t
.
e
xpr
=
P
.
ParseExpression
(
1
);
t
.
E
xpr
=
P
.
ParseExpression
(
1
);
}
P
.
Expect
(
Scanner
.
RBRACK
);
t
.
e
lt
=
P
.
ParseType
();
t
.
E
lt
=
P
.
ParseType
();
P
.
Ecart
();
return
t
;
...
...
@@ -394,19 +394,19 @@ func (P *Parser) ParseChannelType() *AST.Type {
P
.
Trace
(
"ChannelType"
);
t
:=
AST
.
NewType
(
P
.
pos
,
AST
.
CHANNEL
);
t
.
m
ode
=
AST
.
FULL
;
t
.
M
ode
=
AST
.
FULL
;
if
P
.
tok
==
Scanner
.
CHAN
{
P
.
Next
();
if
P
.
tok
==
Scanner
.
ARROW
{
P
.
Next
();
t
.
m
ode
=
AST
.
SEND
;
t
.
M
ode
=
AST
.
SEND
;
}
}
else
{
P
.
Expect
(
Scanner
.
ARROW
);
P
.
Expect
(
Scanner
.
CHAN
);
t
.
m
ode
=
AST
.
RECV
;
t
.
M
ode
=
AST
.
RECV
;
}
t
.
e
lt
=
P
.
ParseVarType
();
t
.
E
lt
=
P
.
ParseVarType
();
P
.
Ecart
();
return
t
;
...
...
@@ -417,8 +417,8 @@ func (P *Parser) ParseVar(expect_ident bool) *AST.Type {
t
:=
AST
.
BadType
;
if
expect_ident
{
x
:=
P
.
ParseIdent
(
nil
);
t
=
AST
.
NewType
(
x
.
p
os
,
AST
.
TYPENAME
);
t
.
e
xpr
=
x
;
t
=
AST
.
NewType
(
x
.
P
os
,
AST
.
TYPENAME
);
t
.
E
xpr
=
x
;
}
else
if
P
.
tok
==
Scanner
.
ELLIPSIS
{
t
=
AST
.
NewType
(
P
.
pos
,
AST
.
ELLIPSIS
);
P
.
Next
();
...
...
@@ -463,11 +463,11 @@ func (P *Parser) ParseVarList(list *array.Array, ellipsis_ok bool) {
// convert the type entries into identifiers
for
i
,
n
:=
i0
,
list
.
Len
();
i
<
n
;
i
++
{
t
:=
list
.
At
(
i
)
.
(
*
AST
.
Type
);
if
t
.
form
==
AST
.
TYPENAME
&&
t
.
expr
.
t
ok
==
Scanner
.
IDENT
{
list
.
Set
(
i
,
t
.
e
xpr
);
if
t
.
Form
==
AST
.
TYPENAME
&&
t
.
Expr
.
T
ok
==
Scanner
.
IDENT
{
list
.
Set
(
i
,
t
.
E
xpr
);
}
else
{
list
.
Set
(
i
,
AST
.
BadExpr
);
P
.
Error
(
t
.
p
os
,
"identifier expected"
);
P
.
Error
(
t
.
P
os
,
"identifier expected"
);
}
}
// add type
...
...
@@ -507,9 +507,9 @@ func (P *Parser) ParseParameters(ellipsis_ok bool) *AST.Type {
t
:=
AST
.
NewType
(
P
.
pos
,
AST
.
STRUCT
);
P
.
Expect
(
Scanner
.
LPAREN
);
if
P
.
tok
!=
Scanner
.
RPAREN
{
t
.
l
ist
=
P
.
ParseParameterList
(
ellipsis_ok
);
t
.
L
ist
=
P
.
ParseParameterList
(
ellipsis_ok
);
}
t
.
e
nd
=
P
.
pos
;
t
.
E
nd
=
P
.
pos
;
P
.
Expect
(
Scanner
.
RPAREN
);
P
.
Ecart
();
...
...
@@ -543,9 +543,9 @@ func (P *Parser) ParseResult() *AST.Type {
typ
:=
P
.
TryType
();
if
typ
!=
nil
{
t
=
AST
.
NewType
(
P
.
pos
,
AST
.
STRUCT
);
t
.
l
ist
=
array
.
New
(
0
);
t
.
l
ist
.
Push
(
AST
.
NewTypeExpr
(
typ
));
t
.
e
nd
=
P
.
pos
;
t
.
L
ist
=
array
.
New
(
0
);
t
.
L
ist
.
Push
(
AST
.
NewTypeExpr
(
typ
));
t
.
E
nd
=
P
.
pos
;
}
}
...
...
@@ -567,9 +567,9 @@ func (P *Parser) ParseFunctionType() *AST.Type {
P
.
scope_lev
++
;
t
:=
AST
.
NewType
(
P
.
pos
,
AST
.
FUNCTION
);
t
.
list
=
P
.
ParseParameters
(
true
)
.
l
ist
;
// TODO find better solution
t
.
e
nd
=
P
.
pos
;
t
.
e
lt
=
P
.
ParseResult
();
t
.
List
=
P
.
ParseParameters
(
true
)
.
L
ist
;
// TODO find better solution
t
.
E
nd
=
P
.
pos
;
t
.
E
lt
=
P
.
ParseResult
();
P
.
scope_lev
--
;
P
.
CloseScope
();
...
...
@@ -605,14 +605,14 @@ func (P *Parser) ParseInterfaceType() *AST.Type {
P
.
OpenScope
();
P
.
scope_lev
++
;
t
.
l
ist
=
array
.
New
(
0
);
t
.
L
ist
=
array
.
New
(
0
);
for
P
.
tok
==
Scanner
.
IDENT
{
P
.
ParseMethodSpec
(
t
.
l
ist
);
P
.
ParseMethodSpec
(
t
.
L
ist
);
if
P
.
tok
!=
Scanner
.
RBRACE
{
P
.
Expect
(
Scanner
.
SEMICOLON
);
}
}
t
.
e
nd
=
P
.
pos
;
t
.
E
nd
=
P
.
pos
;
P
.
scope_lev
--
;
P
.
CloseScope
();
...
...
@@ -630,9 +630,9 @@ func (P *Parser) ParseMapType() *AST.Type {
t
:=
AST
.
NewType
(
P
.
pos
,
AST
.
MAP
);
P
.
Expect
(
Scanner
.
MAP
);
P
.
Expect
(
Scanner
.
LBRACK
);
t
.
k
ey
=
P
.
ParseVarType
();
t
.
K
ey
=
P
.
ParseVarType
();
P
.
Expect
(
Scanner
.
RBRACK
);
t
.
e
lt
=
P
.
ParseVarType
();
t
.
E
lt
=
P
.
ParseVarType
();
P
.
Ecart
();
return
t
;
...
...
@@ -651,12 +651,12 @@ func (P *Parser) ParseStructType() *AST.Type {
P
.
OpenScope
();
P
.
scope_lev
++
;
t
.
l
ist
=
array
.
New
(
0
);
t
.
L
ist
=
array
.
New
(
0
);
for
P
.
tok
!=
Scanner
.
RBRACE
&&
P
.
tok
!=
Scanner
.
EOF
{
P
.
ParseVarList
(
t
.
l
ist
,
false
);
P
.
ParseVarList
(
t
.
L
ist
,
false
);
if
P
.
tok
==
Scanner
.
STRING
{
// ParseOperand takes care of string concatenation
t
.
l
ist
.
Push
(
P
.
ParseOperand
());
t
.
L
ist
.
Push
(
P
.
ParseOperand
());
}
if
P
.
tok
==
Scanner
.
SEMICOLON
{
P
.
Next
();
...
...
@@ -665,7 +665,7 @@ func (P *Parser) ParseStructType() *AST.Type {
}
}
P
.
OptSemicolon
();
t
.
e
nd
=
P
.
pos
;
t
.
E
nd
=
P
.
pos
;
P
.
scope_lev
--
;
P
.
CloseScope
();
...
...
@@ -682,7 +682,7 @@ func (P *Parser) ParsePointerType() *AST.Type {
t
:=
AST
.
NewType
(
P
.
pos
,
AST
.
POINTER
);
P
.
Expect
(
Scanner
.
MUL
);
t
.
e
lt
=
P
.
ParseType
();
t
.
E
lt
=
P
.
ParseType
();
P
.
Ecart
();
return
t
;
...
...
@@ -775,7 +775,7 @@ func (P *Parser) ParseExpressionList() *AST.Expr {
x
=
P
.
NewExpr
(
pos
,
Scanner
.
COMMA
,
x
,
y
);
first
=
false
;
}
else
{
x
.
y
=
P
.
NewExpr
(
pos
,
Scanner
.
COMMA
,
x
.
y
,
y
);
x
.
Y
=
P
.
NewExpr
(
pos
,
Scanner
.
COMMA
,
x
.
Y
,
y
);
}
}
...
...
@@ -790,10 +790,10 @@ func (P *Parser) ParseFunctionLit() *AST.Expr {
val
:=
AST
.
NewObject
(
P
.
pos
,
AST
.
NONE
,
""
);
x
:=
AST
.
NewLit
(
Scanner
.
FUNC
,
val
);
P
.
Expect
(
Scanner
.
FUNC
);
val
.
t
yp
=
P
.
ParseFunctionType
();
val
.
T
yp
=
P
.
ParseFunctionType
();
P
.
expr_lev
++
;
P
.
scope_lev
++
;
val
.
block
,
val
.
e
nd
=
P
.
ParseBlock
();
val
.
Block
,
val
.
E
nd
=
P
.
ParseBlock
();
P
.
scope_lev
--
;
P
.
expr_lev
--
;
...
...
@@ -813,7 +813,7 @@ func (P *Parser) ParseNewCall() *AST.Expr {
x.t = P.ParseType();
if P.tok == Scanner.COMMA {
P.Next();
x.
y
= P.ParseExpressionList();
x.
Y
= P.ParseExpressionList();
}
P.expr_lev--;
P.Expect(Scanner.RPAREN);
...
...
@@ -845,11 +845,11 @@ func (P *Parser) ParseOperand() *AST.Expr {
val
:=
AST
.
NewObject
(
P
.
pos
,
AST
.
NONE
,
P
.
val
);
x
=
AST
.
NewLit
(
P
.
tok
,
val
);
P
.
Next
();
if
x
.
t
ok
==
Scanner
.
STRING
{
if
x
.
T
ok
==
Scanner
.
STRING
{
// TODO should remember the list instead of
// concatenate the strings here
for
;
P
.
tok
==
Scanner
.
STRING
;
P
.
Next
()
{
x
.
obj
.
i
dent
+=
P
.
val
;
x
.
Obj
.
I
dent
+=
P
.
val
;
}
}
...
...
@@ -878,11 +878,11 @@ func (P *Parser) ParseSelectorOrTypeGuard(x *AST.Expr) *AST.Expr {
P
.
Expect
(
Scanner
.
PERIOD
);
if
P
.
tok
==
Scanner
.
IDENT
{
x
.
y
=
P
.
ParseIdent
(
nil
);
x
.
Y
=
P
.
ParseIdent
(
nil
);
}
else
{
P
.
Expect
(
Scanner
.
LPAREN
);
x
.
y
=
AST
.
NewTypeExpr
(
P
.
ParseType
());
x
.
Y
=
AST
.
NewTypeExpr
(
P
.
ParseType
());
P
.
Expect
(
Scanner
.
RPAREN
);
}
...
...
@@ -916,25 +916,25 @@ func (P *Parser) ParseCall(x0 *AST.Expr) *AST.Expr {
if
P
.
tok
!=
Scanner
.
RPAREN
{
P
.
expr_lev
++
;
var
t
*
AST
.
Type
;
if
x0
.
tok
==
Scanner
.
IDENT
&&
(
x0
.
obj
.
ident
==
"new"
||
x0
.
obj
.
i
dent
==
"make"
)
{
if
x0
.
Tok
==
Scanner
.
IDENT
&&
(
x0
.
Obj
.
Ident
==
"new"
||
x0
.
Obj
.
I
dent
==
"make"
)
{
// heuristic: assume it's a new(T) or make(T, ...) call, try to parse a type
t
=
P
.
TryType
();
}
if
t
!=
nil
{
// we found a type
x
.
y
=
AST
.
NewTypeExpr
(
t
);
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
;
z
.
X
=
x
.
Y
;
x
.
Y
=
z
;
}
}
else
{
// normal argument list
x
.
y
=
P
.
ParseExpressionList
();
x
.
Y
=
P
.
ParseExpressionList
();
}
P
.
expr_lev
--
;
}
...
...
@@ -953,7 +953,7 @@ func (P *Parser) ParseCompositeElements() *AST.Expr {
// first element determines mode
singles
:=
true
;
if
x
.
t
ok
==
Scanner
.
COLON
{
if
x
.
T
ok
==
Scanner
.
COLON
{
singles
=
false
;
}
...
...
@@ -962,12 +962,12 @@ func (P *Parser) ParseCompositeElements() *AST.Expr {
y
:=
P
.
ParseExpression
(
0
);
if
singles
{
if
y
.
t
ok
==
Scanner
.
COLON
{
P
.
Error
(
y
.
x
.
p
os
,
"single value expected; found pair"
);
if
y
.
T
ok
==
Scanner
.
COLON
{
P
.
Error
(
y
.
X
.
P
os
,
"single value expected; found pair"
);
}
}
else
{
if
y
.
t
ok
!=
Scanner
.
COLON
{
P
.
Error
(
y
.
p
os
,
"key:value pair expected; found single value"
);
if
y
.
T
ok
!=
Scanner
.
COLON
{
P
.
Error
(
y
.
P
os
,
"key:value pair expected; found single value"
);
}
}
...
...
@@ -975,8 +975,8 @@ func (P *Parser) ParseCompositeElements() *AST.Expr {
x
=
P
.
NewExpr
(
pos
,
Scanner
.
COMMA
,
x
,
y
);
last
=
x
;
}
else
{
last
.
y
=
P
.
NewExpr
(
pos
,
Scanner
.
COMMA
,
last
.
y
,
y
);
last
=
last
.
y
;
last
.
Y
=
P
.
NewExpr
(
pos
,
Scanner
.
COMMA
,
last
.
Y
,
y
);
last
=
last
.
Y
;
}
if
P
.
tok
==
Scanner
.
COMMA
{
...
...
@@ -996,11 +996,11 @@ func (P *Parser) ParseCompositeLit(t *AST.Type) *AST.Expr {
P
.
Trace
(
"CompositeLit"
);
x
:=
P
.
NewExpr
(
P
.
pos
,
Scanner
.
LBRACE
,
nil
,
nil
);
x
.
obj
=
AST
.
NewObject
(
t
.
p
os
,
AST
.
TYPE
,
""
);
x
.
obj
.
t
yp
=
t
;
x
.
Obj
=
AST
.
NewObject
(
t
.
P
os
,
AST
.
TYPE
,
""
);
x
.
Obj
.
T
yp
=
t
;
P
.
Expect
(
Scanner
.
LBRACE
);
if
P
.
tok
!=
Scanner
.
RBRACE
{
x
.
y
=
P
.
ParseCompositeElements
();
x
.
Y
=
P
.
ParseCompositeElements
();
}
P
.
Expect
(
Scanner
.
RBRACE
);
...
...
@@ -1024,7 +1024,7 @@ func (P *Parser) ParsePrimaryExpr() *AST.Expr {
// (composites inside control clauses must be parenthesized)
var
t
*
AST
.
Type
;
if
P
.
expr_lev
>=
0
{
t
=
E
xprType
(
x
);
t
=
e
xprType
(
x
);
}
if
t
!=
nil
{
x
=
P
.
ParseCompositeLit
(
t
);
...
...
@@ -1050,10 +1050,10 @@ func (P *Parser) ParseUnaryExpr() *AST.Expr {
pos
,
tok
:=
P
.
pos
,
P
.
tok
;
P
.
Next
();
y
:=
P
.
ParseUnaryExpr
();
if
tok
==
Scanner
.
MUL
&&
y
.
t
ok
==
Scanner
.
TYPE
{
if
tok
==
Scanner
.
MUL
&&
y
.
T
ok
==
Scanner
.
TYPE
{
// pointer type
t
:=
AST
.
NewType
(
pos
,
AST
.
POINTER
);
t
.
elt
=
y
.
obj
.
t
yp
;
t
.
Elt
=
y
.
Obj
.
T
yp
;
x
=
AST
.
NewTypeExpr
(
t
);
}
else
{
x
=
P
.
NewExpr
(
pos
,
tok
,
nil
,
y
);
...
...
@@ -1129,9 +1129,9 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat {
case
Scanner
.
COLON
:
// label declaration
s
=
AST
.
NewStat
(
P
.
pos
,
Scanner
.
COLON
);
s
.
e
xpr
=
x
;
s
.
E
xpr
=
x
;
if
x
.
Len
()
!=
1
{
P
.
Error
(
x
.
p
os
,
"illegal label declaration"
);
P
.
Error
(
x
.
P
os
,
"illegal label declaration"
);
}
P
.
Next
();
// consume ":"
P
.
opt_semi
=
true
;
...
...
@@ -1156,22 +1156,22 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat {
}
else
{
y
=
P
.
ParseExpressionList
();
if
is_range
{
P
.
Error
(
y
.
p
os
,
"expected 'range', found expression"
);
P
.
Error
(
y
.
P
os
,
"expected 'range', found expression"
);
}
if
xl
,
yl
:=
x
.
Len
(),
y
.
Len
();
xl
>
1
&&
yl
>
1
&&
xl
!=
yl
{
P
.
Error
(
x
.
p
os
,
"arity of lhs doesn't match rhs"
);
P
.
Error
(
x
.
P
os
,
"arity of lhs doesn't match rhs"
);
}
}
s
=
AST
.
NewStat
(
x
.
p
os
,
Scanner
.
EXPRSTAT
);
s
.
e
xpr
=
AST
.
NewExpr
(
pos
,
tok
,
x
,
y
);
s
=
AST
.
NewStat
(
x
.
P
os
,
Scanner
.
EXPRSTAT
);
s
.
E
xpr
=
AST
.
NewExpr
(
pos
,
tok
,
x
,
y
);
case
Scanner
.
RANGE
:
pos
:=
P
.
pos
;
P
.
Next
();
y
:=
P
.
ParseExpression
(
1
);
y
=
P
.
NewExpr
(
pos
,
Scanner
.
RANGE
,
nil
,
y
);
s
=
AST
.
NewStat
(
x
.
p
os
,
Scanner
.
EXPRSTAT
);
s
.
e
xpr
=
AST
.
NewExpr
(
pos
,
Scanner
.
DEFINE
,
x
,
y
);
s
=
AST
.
NewStat
(
x
.
P
os
,
Scanner
.
EXPRSTAT
);
s
.
E
xpr
=
AST
.
NewExpr
(
pos
,
Scanner
.
DEFINE
,
x
,
y
);
default
:
var
pos
,
tok
int
;
...
...
@@ -1179,12 +1179,12 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat {
pos
,
tok
=
P
.
pos
,
P
.
tok
;
P
.
Next
();
}
else
{
pos
,
tok
=
x
.
p
os
,
Scanner
.
EXPRSTAT
;
pos
,
tok
=
x
.
P
os
,
Scanner
.
EXPRSTAT
;
}
s
=
AST
.
NewStat
(
pos
,
tok
);
s
.
e
xpr
=
x
;
s
.
E
xpr
=
x
;
if
x
.
Len
()
!=
1
{
P
.
Error
(
x
.
p
os
,
"only one expression allowed"
);
P
.
Error
(
x
.
P
os
,
"only one expression allowed"
);
}
}
...
...
@@ -1198,7 +1198,7 @@ func (P *Parser) ParseGoStat() *AST.Stat {
s
:=
AST
.
NewStat
(
P
.
pos
,
Scanner
.
GO
);
P
.
Expect
(
Scanner
.
GO
);
s
.
e
xpr
=
P
.
ParseExpression
(
1
);
s
.
E
xpr
=
P
.
ParseExpression
(
1
);
P
.
Ecart
();
return
s
;
...
...
@@ -1211,7 +1211,7 @@ func (P *Parser) ParseReturnStat() *AST.Stat {
s
:=
AST
.
NewStat
(
P
.
pos
,
Scanner
.
RETURN
);
P
.
Expect
(
Scanner
.
RETURN
);
if
P
.
tok
!=
Scanner
.
SEMICOLON
&&
P
.
tok
!=
Scanner
.
RBRACE
{
s
.
e
xpr
=
P
.
ParseExpressionList
();
s
.
E
xpr
=
P
.
ParseExpressionList
();
}
P
.
Ecart
();
...
...
@@ -1225,7 +1225,7 @@ func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat {
s
:=
AST
.
NewStat
(
P
.
pos
,
tok
);
P
.
Expect
(
tok
);
if
tok
!=
Scanner
.
FALLTHROUGH
&&
P
.
tok
==
Scanner
.
IDENT
{
s
.
e
xpr
=
P
.
ParseIdent
(
P
.
top_scope
);
s
.
E
xpr
=
P
.
ParseIdent
(
P
.
top_scope
);
}
P
.
Ecart
();
...
...
@@ -1242,23 +1242,23 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat {
prev_lev
:=
P
.
expr_lev
;
P
.
expr_lev
=
-
1
;
if
P
.
tok
!=
Scanner
.
SEMICOLON
{
s
.
i
nit
=
P
.
ParseSimpleStat
(
keyword
==
Scanner
.
FOR
);
s
.
I
nit
=
P
.
ParseSimpleStat
(
keyword
==
Scanner
.
FOR
);
// TODO check for range clause and exit if found
}
if
P
.
tok
==
Scanner
.
SEMICOLON
{
P
.
Next
();
if
P
.
tok
!=
Scanner
.
SEMICOLON
&&
P
.
tok
!=
Scanner
.
LBRACE
{
s
.
e
xpr
=
P
.
ParseExpression
(
1
);
s
.
E
xpr
=
P
.
ParseExpression
(
1
);
}
if
keyword
==
Scanner
.
FOR
{
P
.
Expect
(
Scanner
.
SEMICOLON
);
if
P
.
tok
!=
Scanner
.
LBRACE
{
s
.
p
ost
=
P
.
ParseSimpleStat
(
false
);
s
.
P
ost
=
P
.
ParseSimpleStat
(
false
);
}
}
}
else
{
if
s
.
i
nit
!=
nil
{
// guard in case of errors
s
.
expr
,
s
.
init
=
s
.
init
.
e
xpr
,
nil
;
if
s
.
I
nit
!=
nil
{
// guard in case of errors
s
.
Expr
,
s
.
Init
=
s
.
Init
.
E
xpr
,
nil
;
}
}
P
.
expr_lev
=
prev_lev
;
...
...
@@ -1274,7 +1274,7 @@ func (P *Parser) ParseIfStat() *AST.Stat {
P
.
OpenScope
();
s
:=
P
.
ParseControlClause
(
Scanner
.
IF
);
s
.
block
,
s
.
e
nd
=
P
.
ParseBlock
();
s
.
Block
,
s
.
E
nd
=
P
.
ParseBlock
();
if
P
.
tok
==
Scanner
.
ELSE
{
P
.
Next
();
s1
:=
AST
.
BadStat
;
...
...
@@ -1284,20 +1284,20 @@ func (P *Parser) ParseIfStat() *AST.Stat {
s1
=
P
.
ParseStatement
();
if
s1
!=
nil
{
// not the empty statement
if
s1
.
t
ok
!=
Scanner
.
LBRACE
{
if
s1
.
T
ok
!=
Scanner
.
LBRACE
{
// wrap in a block if we don't have one
b
:=
AST
.
NewStat
(
P
.
pos
,
Scanner
.
LBRACE
);
b
.
b
lock
=
array
.
New
(
0
);
b
.
b
lock
.
Push
(
s1
);
b
.
B
lock
=
array
.
New
(
0
);
b
.
B
lock
.
Push
(
s1
);
s1
=
b
;
}
s
.
p
ost
=
s1
;
s
.
P
ost
=
s1
;
}
}
else
{
s1
=
AST
.
NewStat
(
P
.
pos
,
Scanner
.
LBRACE
);
s1
.
block
,
s1
.
e
nd
=
P
.
ParseBlock
();
s1
.
Block
,
s1
.
E
nd
=
P
.
ParseBlock
();
}
s
.
p
ost
=
s1
;
s
.
P
ost
=
s1
;
}
P
.
CloseScope
();
...
...
@@ -1311,7 +1311,7 @@ func (P *Parser) ParseForStat() *AST.Stat {
P
.
OpenScope
();
s
:=
P
.
ParseControlClause
(
Scanner
.
FOR
);
s
.
block
,
s
.
e
nd
=
P
.
ParseBlock
();
s
.
Block
,
s
.
E
nd
=
P
.
ParseBlock
();
P
.
CloseScope
();
P
.
Ecart
();
...
...
@@ -1325,7 +1325,7 @@ func (P *Parser) ParseCase() *AST.Stat {
s
:=
AST
.
NewStat
(
P
.
pos
,
P
.
tok
);
if
P
.
tok
==
Scanner
.
CASE
{
P
.
Next
();
s
.
e
xpr
=
P
.
ParseExpressionList
();
s
.
E
xpr
=
P
.
ParseExpressionList
();
}
else
{
P
.
Expect
(
Scanner
.
DEFAULT
);
}
...
...
@@ -1341,7 +1341,7 @@ func (P *Parser) ParseCaseClause() *AST.Stat {
s
:=
P
.
ParseCase
();
if
P
.
tok
!=
Scanner
.
CASE
&&
P
.
tok
!=
Scanner
.
DEFAULT
&&
P
.
tok
!=
Scanner
.
RBRACE
{
s
.
b
lock
=
P
.
ParseStatementList
();
s
.
B
lock
=
P
.
ParseStatementList
();
}
P
.
Ecart
();
...
...
@@ -1354,12 +1354,12 @@ func (P *Parser) ParseSwitchStat() *AST.Stat {
P
.
OpenScope
();
s
:=
P
.
ParseControlClause
(
Scanner
.
SWITCH
);
s
.
b
lock
=
array
.
New
(
0
);
s
.
B
lock
=
array
.
New
(
0
);
P
.
Expect
(
Scanner
.
LBRACE
);
for
P
.
tok
!=
Scanner
.
RBRACE
&&
P
.
tok
!=
Scanner
.
EOF
{
s
.
b
lock
.
Push
(
P
.
ParseCaseClause
());
s
.
B
lock
.
Push
(
P
.
ParseCaseClause
());
}
s
.
e
nd
=
P
.
pos
;
s
.
E
nd
=
P
.
pos
;
P
.
Expect
(
Scanner
.
RBRACE
);
P
.
opt_semi
=
true
;
P
.
CloseScope
();
...
...
@@ -1386,7 +1386,7 @@ func (P *Parser) ParseCommCase() *AST.Stat {
P
.
Expect
(
Scanner
.
ARROW
);
// use Expect() error handling
}
}
s
.
e
xpr
=
x
;
s
.
E
xpr
=
x
;
}
else
{
P
.
Expect
(
Scanner
.
DEFAULT
);
}
...
...
@@ -1402,7 +1402,7 @@ func (P *Parser) ParseCommClause() *AST.Stat {
s
:=
P
.
ParseCommCase
();
if
P
.
tok
!=
Scanner
.
CASE
&&
P
.
tok
!=
Scanner
.
DEFAULT
&&
P
.
tok
!=
Scanner
.
RBRACE
{
s
.
b
lock
=
P
.
ParseStatementList
();
s
.
B
lock
=
P
.
ParseStatementList
();
}
P
.
Ecart
();
...
...
@@ -1414,11 +1414,11 @@ func (P *Parser) ParseSelectStat() *AST.Stat {
P
.
Trace
(
"SelectStat"
);
s
:=
AST
.
NewStat
(
P
.
pos
,
Scanner
.
SELECT
);
s
.
b
lock
=
array
.
New
(
0
);
s
.
B
lock
=
array
.
New
(
0
);
P
.
Expect
(
Scanner
.
SELECT
);
P
.
Expect
(
Scanner
.
LBRACE
);
for
P
.
tok
!=
Scanner
.
RBRACE
&&
P
.
tok
!=
Scanner
.
EOF
{
s
.
b
lock
.
Push
(
P
.
ParseCommClause
());
s
.
B
lock
.
Push
(
P
.
ParseCommClause
());
}
P
.
Expect
(
Scanner
.
RBRACE
);
P
.
opt_semi
=
true
;
...
...
@@ -1435,8 +1435,8 @@ func (P *Parser) ParseRangeStat() *AST.Stat {
P
.
Expect
(
Scanner
.
RANGE
);
P
.
ParseIdentList
();
P
.
Expect
(
Scanner
.
DEFINE
);
s
.
e
xpr
=
P
.
ParseExpression
(
1
);
s
.
block
,
s
.
e
nd
=
P
.
ParseBlock
();
s
.
E
xpr
=
P
.
ParseExpression
(
1
);
s
.
Block
,
s
.
E
nd
=
P
.
ParseBlock
();
P
.
Ecart
();
return
s
;
...
...
@@ -1451,7 +1451,7 @@ func (P *Parser) ParseStatement() *AST.Stat {
switch
P
.
tok
{
case
Scanner
.
CONST
,
Scanner
.
TYPE
,
Scanner
.
VAR
:
s
=
AST
.
NewStat
(
P
.
pos
,
P
.
tok
);
s
.
d
ecl
=
P
.
ParseDeclaration
();
s
.
D
ecl
=
P
.
ParseDeclaration
();
case
Scanner
.
FUNC
:
// for now we do not allow local function declarations,
// instead we assume this starts a function literal
...
...
@@ -1470,7 +1470,7 @@ func (P *Parser) ParseStatement() *AST.Stat {
s
=
P
.
ParseControlFlowStat
(
P
.
tok
);
case
Scanner
.
LBRACE
:
s
=
AST
.
NewStat
(
P
.
pos
,
Scanner
.
LBRACE
);
s
.
block
,
s
.
e
nd
=
P
.
ParseBlock
();
s
.
Block
,
s
.
E
nd
=
P
.
ParseBlock
();
case
Scanner
.
IF
:
s
=
P
.
ParseIfStat
();
case
Scanner
.
FOR
:
...
...
@@ -1505,20 +1505,20 @@ func (P *Parser) ParseImportSpec(pos int) *AST.Decl {
P
.
Error
(
P
.
pos
,
`"import ." not yet handled properly`
);
P
.
Next
();
}
else
if
P
.
tok
==
Scanner
.
IDENT
{
d
.
i
dent
=
P
.
ParseIdent
(
nil
);
d
.
I
dent
=
P
.
ParseIdent
(
nil
);
}
if
P
.
tok
==
Scanner
.
STRING
{
// TODO eventually the scanner should strip the quotes
val
:=
AST
.
NewObject
(
P
.
pos
,
AST
.
NONE
,
P
.
val
);
d
.
v
al
=
AST
.
NewLit
(
Scanner
.
STRING
,
val
);
d
.
V
al
=
AST
.
NewLit
(
Scanner
.
STRING
,
val
);
P
.
Next
();
}
else
{
P
.
Expect
(
Scanner
.
STRING
);
// use Expect() error handling
}
if
d
.
i
dent
!=
nil
{
P
.
Declare
(
d
.
i
dent
,
AST
.
PACKAGE
);
if
d
.
I
dent
!=
nil
{
P
.
Declare
(
d
.
I
dent
,
AST
.
PACKAGE
);
}
P
.
Ecart
();
...
...
@@ -1530,15 +1530,15 @@ func (P *Parser) ParseConstSpec(exported bool, pos int) *AST.Decl {
P
.
Trace
(
"ConstSpec"
);
d
:=
AST
.
NewDecl
(
pos
,
Scanner
.
CONST
,
exported
);
d
.
i
dent
=
P
.
ParseIdentList
();
d
.
t
yp
=
P
.
TryType
();
d
.
I
dent
=
P
.
ParseIdentList
();
d
.
T
yp
=
P
.
TryType
();
if
P
.
tok
==
Scanner
.
ASSIGN
{
P
.
Next
();
d
.
v
al
=
P
.
ParseExpressionList
();
d
.
V
al
=
P
.
ParseExpressionList
();
}
P
.
Declare
(
d
.
i
dent
,
AST
.
CONST
);
P
.
VerifyExport
(
d
.
i
dent
,
exported
);
P
.
Declare
(
d
.
I
dent
,
AST
.
CONST
);
P
.
VerifyExport
(
d
.
I
dent
,
exported
);
P
.
Ecart
();
return
d
;
...
...
@@ -1549,11 +1549,11 @@ func (P *Parser) ParseTypeSpec(exported bool, pos int) *AST.Decl {
P
.
Trace
(
"TypeSpec"
);
d
:=
AST
.
NewDecl
(
pos
,
Scanner
.
TYPE
,
exported
);
d
.
i
dent
=
P
.
ParseIdent
(
nil
);
d
.
t
yp
=
P
.
ParseType
();
d
.
I
dent
=
P
.
ParseIdent
(
nil
);
d
.
T
yp
=
P
.
ParseType
();
P
.
opt_semi
=
true
;
P
.
VerifyExport
(
d
.
i
dent
,
exported
);
P
.
VerifyExport
(
d
.
I
dent
,
exported
);
P
.
Ecart
();
return
d
;
...
...
@@ -1564,20 +1564,20 @@ func (P *Parser) ParseVarSpec(exported bool, pos int) *AST.Decl {
P
.
Trace
(
"VarSpec"
);
d
:=
AST
.
NewDecl
(
pos
,
Scanner
.
VAR
,
exported
);
d
.
i
dent
=
P
.
ParseIdentList
();
d
.
I
dent
=
P
.
ParseIdentList
();
if
P
.
tok
==
Scanner
.
ASSIGN
{
P
.
Next
();
d
.
v
al
=
P
.
ParseExpressionList
();
d
.
V
al
=
P
.
ParseExpressionList
();
}
else
{
d
.
t
yp
=
P
.
ParseVarType
();
d
.
T
yp
=
P
.
ParseVarType
();
if
P
.
tok
==
Scanner
.
ASSIGN
{
P
.
Next
();
d
.
v
al
=
P
.
ParseExpressionList
();
d
.
V
al
=
P
.
ParseExpressionList
();
}
}
P
.
Declare
(
d
.
i
dent
,
AST
.
VAR
);
P
.
VerifyExport
(
d
.
i
dent
,
exported
);
P
.
Declare
(
d
.
I
dent
,
AST
.
VAR
);
P
.
VerifyExport
(
d
.
I
dent
,
exported
);
P
.
Ecart
();
return
d
;
...
...
@@ -1606,16 +1606,16 @@ func (P *Parser) ParseDecl(exported bool, keyword int) *AST.Decl {
if
P
.
tok
==
Scanner
.
LPAREN
{
P
.
Next
();
d
=
AST
.
NewDecl
(
pos
,
keyword
,
exported
);
d
.
l
ist
=
array
.
New
(
0
);
d
.
L
ist
=
array
.
New
(
0
);
for
P
.
tok
!=
Scanner
.
RPAREN
&&
P
.
tok
!=
Scanner
.
EOF
{
d
.
l
ist
.
Push
(
P
.
ParseSpec
(
exported
,
pos
,
keyword
));
d
.
L
ist
.
Push
(
P
.
ParseSpec
(
exported
,
pos
,
keyword
));
if
P
.
tok
==
Scanner
.
SEMICOLON
{
P
.
Next
();
}
else
{
break
;
}
}
d
.
e
nd
=
P
.
pos
;
d
.
E
nd
=
P
.
pos
;
P
.
Expect
(
Scanner
.
RPAREN
);
P
.
opt_semi
=
true
;
...
...
@@ -1647,23 +1647,23 @@ func (P *Parser) ParseFunctionDecl(exported bool) *AST.Decl {
if
P
.
tok
==
Scanner
.
LPAREN
{
pos
:=
P
.
pos
;
recv
=
P
.
ParseParameters
(
true
);
if
recv
.
n
fields
()
!=
1
{
if
recv
.
N
fields
()
!=
1
{
P
.
Error
(
pos
,
"must have exactly one receiver"
);
}
}
d
.
i
dent
=
P
.
ParseIdent
(
nil
);
d
.
t
yp
=
P
.
ParseFunctionType
();
d
.
typ
.
k
ey
=
recv
;
d
.
I
dent
=
P
.
ParseIdent
(
nil
);
d
.
T
yp
=
P
.
ParseFunctionType
();
d
.
Typ
.
K
ey
=
recv
;
if
P
.
tok
==
Scanner
.
LBRACE
{
P
.
scope_lev
++
;
d
.
list
,
d
.
e
nd
=
P
.
ParseBlock
();
d
.
List
,
d
.
E
nd
=
P
.
ParseBlock
();
P
.
scope_lev
--
;
}
if
recv
==
nil
||
exported
{
P
.
VerifyExport
(
d
.
i
dent
,
exported
);
P
.
VerifyExport
(
d
.
I
dent
,
exported
);
}
P
.
Ecart
();
...
...
@@ -1675,7 +1675,7 @@ func (P *Parser) ParseExportDecl() *AST.Decl {
P
.
Trace
(
"ExportDecl"
);
d
:=
AST
.
NewDecl
(
P
.
pos
,
Scanner
.
EXPORT
,
false
);
d
.
i
dent
=
P
.
ParseIdentList
();
d
.
I
dent
=
P
.
ParseIdentList
();
P
.
Ecart
();
return
d
;
...
...
@@ -1735,25 +1735,25 @@ func (P *Parser) ParseProgram() *AST.Program {
P
.
OpenScope
();
p
:=
AST
.
NewProgram
(
P
.
pos
);
P
.
Expect
(
Scanner
.
PACKAGE
);
p
.
i
dent
=
P
.
ParseIdent
(
nil
);
p
.
I
dent
=
P
.
ParseIdent
(
nil
);
// package body
{
P
.
OpenScope
();
p
.
d
ecls
=
array
.
New
(
0
);
p
.
D
ecls
=
array
.
New
(
0
);
for
P
.
tok
==
Scanner
.
IMPORT
{
p
.
d
ecls
.
Push
(
P
.
ParseDecl
(
false
,
Scanner
.
IMPORT
));
p
.
D
ecls
.
Push
(
P
.
ParseDecl
(
false
,
Scanner
.
IMPORT
));
P
.
OptSemicolon
();
}
if
!
P
.
deps
{
for
P
.
tok
!=
Scanner
.
EOF
{
p
.
d
ecls
.
Push
(
P
.
ParseDeclaration
());
p
.
D
ecls
.
Push
(
P
.
ParseDeclaration
());
P
.
OptSemicolon
();
}
}
P
.
CloseScope
();
}
p
.
c
omments
=
P
.
comments
;
p
.
C
omments
=
P
.
comments
;
P
.
CloseScope
();
P
.
Ecart
();
...
...
usr/gri/pretty/platform.go
View file @
2527bba9
...
...
@@ -17,7 +17,7 @@ export var
USER
string
;
func
G
etEnv
(
key
string
)
string
{
func
g
etEnv
(
key
string
)
string
{
n
:=
len
(
key
);
for
i
:=
0
;
i
<
sys
.
envc
();
i
++
{
v
:=
sys
.
envv
(
i
);
...
...
@@ -30,10 +30,10 @@ func GetEnv(key string) string {
func
init
()
{
GOARCH
=
G
etEnv
(
"GOARCH"
);
GOOS
=
G
etEnv
(
"GOOS"
);
GOROOT
=
G
etEnv
(
"GOROOT"
);
USER
=
G
etEnv
(
"USER"
);
GOARCH
=
g
etEnv
(
"GOARCH"
);
GOOS
=
g
etEnv
(
"GOOS"
);
GOROOT
=
g
etEnv
(
"GOROOT"
);
USER
=
g
etEnv
(
"USER"
);
}
...
...
@@ -42,13 +42,13 @@ func init() {
export
const
(
MAGIC_obj_file
=
"@gri-go.7@v0"
;
// make it clear that it cannot be a source file
s
rc_file_ext
=
".go"
;
o
bj_file_ext
=
".7"
;
S
rc_file_ext
=
".go"
;
O
bj_file_ext
=
".7"
;
)
export
func
ReadObjectFile
(
filename
string
)
(
data
string
,
ok
bool
)
{
data
,
ok
=
sys
.
readfile
(
filename
+
o
bj_file_ext
);
data
,
ok
=
sys
.
readfile
(
filename
+
O
bj_file_ext
);
magic
:=
MAGIC_obj_file
;
// TODO remove once len(constant) works
if
ok
&&
len
(
data
)
>=
len
(
magic
)
&&
data
[
0
:
len
(
magic
)]
==
magic
{
return
data
,
ok
;
...
...
@@ -58,13 +58,13 @@ export func ReadObjectFile(filename string) (data string, ok bool) {
export
func
ReadSourceFile
(
name
string
)
(
data
string
,
ok
bool
)
{
name
=
Utils
.
TrimExt
(
name
,
src_file_ext
)
+
s
rc_file_ext
;
name
=
Utils
.
TrimExt
(
name
,
Src_file_ext
)
+
S
rc_file_ext
;
data
,
ok
=
sys
.
readfile
(
name
);
return
data
,
ok
;
}
export
func
WriteObjectFile
(
name
string
,
data
string
)
bool
{
name
=
Utils
.
TrimExt
(
Utils
.
BaseName
(
name
),
src_file_ext
)
+
o
bj_file_ext
;
name
=
Utils
.
TrimExt
(
Utils
.
BaseName
(
name
),
Src_file_ext
)
+
O
bj_file_ext
;
return
sys
.
writefile
(
name
,
data
);
}
usr/gri/pretty/pretty.go
View file @
2527bba9
...
...
@@ -29,7 +29,7 @@ func init() {
}
func
U
sage
()
{
func
u
sage
()
{
print
(
"usage: pretty { flags } { files }
\n
"
);
Flag
.
PrintDefaults
();
sys
.
exit
(
0
);
...
...
@@ -40,7 +40,7 @@ func main() {
Flag
.
Parse
();
if
Flag
.
NFlag
()
==
0
&&
Flag
.
NArg
()
==
0
{
U
sage
();
u
sage
();
}
// process files
...
...
usr/gri/pretty/printer.go
View file @
2527bba9
...
...
@@ -54,7 +54,7 @@ const (
)
type
Printer
struct
{
export
type
Printer
struct
{
// output
text
io
.
Write
;
...
...
@@ -86,7 +86,7 @@ func (P *Printer) HasComment(pos int) bool {
func
(
P
*
Printer
)
NextComment
()
{
P
.
cindex
++
;
if
P
.
comments
!=
nil
&&
P
.
cindex
<
P
.
comments
.
Len
()
{
P
.
cpos
=
P
.
comments
.
At
(
P
.
cindex
)
.
(
*
AST
.
Comment
)
.
p
os
;
P
.
cpos
=
P
.
comments
.
At
(
P
.
cindex
)
.
(
*
AST
.
Comment
)
.
P
os
;
}
else
{
P
.
cpos
=
1
<<
30
;
// infinite
}
...
...
@@ -109,7 +109,7 @@ func (P *Printer) Init(text io.Write, comments *array.Array) {
// ----------------------------------------------------------------------------
// Printing support
func
H
tmlEscape
(
s
string
)
string
{
func
h
tmlEscape
(
s
string
)
string
{
if
*
html
{
var
esc
string
;
for
i
:=
0
;
i
<
len
(
s
);
i
++
{
...
...
@@ -118,7 +118,7 @@ func HtmlEscape(s string) string {
case
'&'
:
esc
=
"&"
;
default
:
continue
;
}
return
s
[
0
:
i
]
+
esc
+
H
tmlEscape
(
s
[
i
+
1
:
len
(
s
)]);
return
s
[
0
:
i
]
+
esc
+
h
tmlEscape
(
s
[
i
+
1
:
len
(
s
)]);
}
}
return
s
;
...
...
@@ -126,7 +126,7 @@ func HtmlEscape(s string) string {
// Reduce contiguous sequences of '\t' in a string to a single '\t'.
func
U
ntabify
(
s
string
)
string
{
func
u
ntabify
(
s
string
)
string
{
for
i
:=
0
;
i
<
len
(
s
);
i
++
{
if
s
[
i
]
==
'\t'
{
j
:=
i
;
...
...
@@ -134,7 +134,7 @@ func Untabify(s string) string {
j
++
;
}
if
j
-
i
>
1
{
// more then one tab
return
s
[
0
:
i
+
1
]
+
U
ntabify
(
s
[
j
:
len
(
s
)]);
return
s
[
0
:
i
+
1
]
+
u
ntabify
(
s
[
j
:
len
(
s
)]);
}
}
}
...
...
@@ -210,7 +210,7 @@ func (P *Printer) TaggedString(pos int, tag, s, endtag string) {
for
;
P
.
HasComment
(
pos
);
P
.
NextComment
()
{
// we have a comment/newline that comes before the string
comment
:=
P
.
comments
.
At
(
P
.
cindex
)
.
(
*
AST
.
Comment
);
ctext
:=
comment
.
t
ext
;
ctext
:=
comment
.
T
ext
;
if
ctext
==
"
\n
"
{
// found a newline in src - count it
...
...
@@ -261,9 +261,9 @@ func (P *Printer) TaggedString(pos int, tag, s, endtag string) {
if
*
debug
{
P
.
Printf
(
"[%d]"
,
P
.
cpos
);
}
// calling
U
ntabify increases the change for idempotent output
// calling
u
ntabify increases the change for idempotent output
// since tabs in comments are also interpreted by tabwriter
P
.
Printf
(
"%s"
,
HtmlEscape
(
U
ntabify
(
ctext
)));
P
.
Printf
(
"%s"
,
htmlEscape
(
u
ntabify
(
ctext
)));
if
ctext
[
1
]
==
'/'
{
//-style comments must end in newline
...
...
@@ -309,7 +309,7 @@ func (P *Printer) TaggedString(pos int, tag, s, endtag string) {
if
*
debug
{
P
.
Printf
(
"[%d]"
,
pos
);
}
P
.
Printf
(
"%s%s%s"
,
tag
,
H
tmlEscape
(
s
),
endtag
);
P
.
Printf
(
"%s%s%s"
,
tag
,
h
tmlEscape
(
s
),
endtag
);
// --------------------------------
// interpret state
...
...
@@ -359,7 +359,7 @@ func (P *Printer) HtmlPrologue(title string) {
"<html>
\n
"
"<head>
\n
"
" <META HTTP-EQUIV=
\"
Content-Type
\"
CONTENT=
\"
text/html; charset=UTF-8
\"
>
\n
"
" <title>"
+
H
tmlEscape
(
title
)
+
"</title>
\n
"
" <title>"
+
h
tmlEscape
(
title
)
+
"</title>
\n
"
" <style type=
\"
text/css
\"
>
\n
"
" </style>
\n
"
"</head>
\n
"
...
...
@@ -384,23 +384,23 @@ func (P *Printer) HtmlEpilogue() {
func
(
P
*
Printer
)
HtmlIdentifier
(
x
*
AST
.
Expr
)
{
if
x
.
t
ok
!=
Scanner
.
IDENT
{
if
x
.
T
ok
!=
Scanner
.
IDENT
{
panic
();
}
obj
:=
x
.
o
bj
;
if
*
html
&&
obj
.
k
ind
!=
AST
.
NONE
{
obj
:=
x
.
O
bj
;
if
*
html
&&
obj
.
K
ind
!=
AST
.
NONE
{
// depending on whether we have a declaration or use, generate different html
// - no need to
H
tmlEscape ident
id
:=
Utils
.
IntToString
(
obj
.
i
d
,
10
);
if
x
.
pos
==
obj
.
p
os
{
// - no need to
h
tmlEscape ident
id
:=
Utils
.
IntToString
(
obj
.
I
d
,
10
);
if
x
.
Pos
==
obj
.
P
os
{
// probably the declaration of x
P
.
TaggedString
(
x
.
pos
,
`<a name="id`
+
id
+
`">`
,
obj
.
i
dent
,
`</a>`
);
P
.
TaggedString
(
x
.
Pos
,
`<a name="id`
+
id
+
`">`
,
obj
.
I
dent
,
`</a>`
);
}
else
{
// probably not the declaration of x
P
.
TaggedString
(
x
.
pos
,
`<a href="#id`
+
id
+
`">`
,
obj
.
i
dent
,
`</a>`
);
P
.
TaggedString
(
x
.
Pos
,
`<a href="#id`
+
id
+
`">`
,
obj
.
I
dent
,
`</a>`
);
}
}
else
{
P
.
String
(
x
.
pos
,
obj
.
i
dent
);
P
.
String
(
x
.
Pos
,
obj
.
I
dent
);
}
}
...
...
@@ -418,14 +418,14 @@ func (P *Printer) Parameters(pos int, list *array.Array) {
for
i
,
n
:=
0
,
list
.
Len
();
i
<
n
;
i
++
{
x
:=
list
.
At
(
i
)
.
(
*
AST
.
Expr
);
if
i
>
0
{
if
prev
==
x
.
t
ok
||
prev
==
Scanner
.
TYPE
{
if
prev
==
x
.
T
ok
||
prev
==
Scanner
.
TYPE
{
P
.
separator
=
comma
;
}
else
{
P
.
separator
=
blank
;
}
}
P
.
Expr
(
x
);
prev
=
x
.
t
ok
;
prev
=
x
.
T
ok
;
}
}
P
.
String
(
0
,
")"
);
...
...
@@ -442,17 +442,17 @@ func (P *Printer) Fields(list *array.Array, end int) {
for
i
,
n
:=
0
,
list
.
Len
();
i
<
n
;
i
++
{
x
:=
list
.
At
(
i
)
.
(
*
AST
.
Expr
);
if
i
>
0
{
if
prev
==
Scanner
.
TYPE
&&
x
.
t
ok
!=
Scanner
.
STRING
||
prev
==
Scanner
.
STRING
{
if
prev
==
Scanner
.
TYPE
&&
x
.
T
ok
!=
Scanner
.
STRING
||
prev
==
Scanner
.
STRING
{
P
.
separator
=
semicolon
;
P
.
newlines
=
1
;
}
else
if
prev
==
x
.
t
ok
{
}
else
if
prev
==
x
.
T
ok
{
P
.
separator
=
comma
;
}
else
{
P
.
separator
=
tab
;
}
}
P
.
Expr
(
x
);
prev
=
x
.
t
ok
;
prev
=
x
.
T
ok
;
}
P
.
newlines
=
1
;
}
...
...
@@ -467,54 +467,54 @@ func (P *Printer) Fields(list *array.Array, end int) {
func
(
P
*
Printer
)
Type
(
t
*
AST
.
Type
)
int
{
separator
:=
semicolon
;
switch
t
.
f
orm
{
switch
t
.
F
orm
{
case
AST
.
TYPENAME
:
P
.
Expr
(
t
.
e
xpr
);
P
.
Expr
(
t
.
E
xpr
);
case
AST
.
ARRAY
:
P
.
String
(
t
.
p
os
,
"["
);
if
t
.
e
xpr
!=
nil
{
P
.
Expr
(
t
.
e
xpr
);
P
.
String
(
t
.
P
os
,
"["
);
if
t
.
E
xpr
!=
nil
{
P
.
Expr
(
t
.
E
xpr
);
}
P
.
String
(
0
,
"]"
);
separator
=
P
.
Type
(
t
.
e
lt
);
separator
=
P
.
Type
(
t
.
E
lt
);
case
AST
.
STRUCT
,
AST
.
INTERFACE
:
switch
t
.
f
orm
{
case
AST
.
STRUCT
:
P
.
String
(
t
.
p
os
,
"struct"
);
case
AST
.
INTERFACE
:
P
.
String
(
t
.
p
os
,
"interface"
);
switch
t
.
F
orm
{
case
AST
.
STRUCT
:
P
.
String
(
t
.
P
os
,
"struct"
);
case
AST
.
INTERFACE
:
P
.
String
(
t
.
P
os
,
"interface"
);
}
if
t
.
l
ist
!=
nil
{
if
t
.
L
ist
!=
nil
{
P
.
separator
=
blank
;
P
.
Fields
(
t
.
list
,
t
.
e
nd
);
P
.
Fields
(
t
.
List
,
t
.
E
nd
);
}
separator
=
none
;
case
AST
.
MAP
:
P
.
String
(
t
.
p
os
,
"map ["
);
P
.
Type
(
t
.
k
ey
);
P
.
String
(
t
.
P
os
,
"map ["
);
P
.
Type
(
t
.
K
ey
);
P
.
String
(
0
,
"]"
);
separator
=
P
.
Type
(
t
.
e
lt
);
separator
=
P
.
Type
(
t
.
E
lt
);
case
AST
.
CHANNEL
:
var
m
string
;
switch
t
.
m
ode
{
switch
t
.
M
ode
{
case
AST
.
FULL
:
m
=
"chan "
;
case
AST
.
RECV
:
m
=
"<-chan "
;
case
AST
.
SEND
:
m
=
"chan <- "
;
}
P
.
String
(
t
.
p
os
,
m
);
separator
=
P
.
Type
(
t
.
e
lt
);
P
.
String
(
t
.
P
os
,
m
);
separator
=
P
.
Type
(
t
.
E
lt
);
case
AST
.
POINTER
:
P
.
String
(
t
.
p
os
,
"*"
);
separator
=
P
.
Type
(
t
.
e
lt
);
P
.
String
(
t
.
P
os
,
"*"
);
separator
=
P
.
Type
(
t
.
E
lt
);
case
AST
.
FUNCTION
:
P
.
Parameters
(
t
.
pos
,
t
.
l
ist
);
if
t
.
e
lt
!=
nil
{
P
.
Parameters
(
t
.
Pos
,
t
.
L
ist
);
if
t
.
E
lt
!=
nil
{
P
.
separator
=
blank
;
list
:=
t
.
elt
.
l
ist
;
list
:=
t
.
Elt
.
L
ist
;
if
list
.
Len
()
>
1
{
P
.
Parameters
(
0
,
list
);
}
else
{
...
...
@@ -524,10 +524,10 @@ func (P *Printer) Type(t *AST.Type) int {
}
case
AST
.
ELLIPSIS
:
P
.
String
(
t
.
p
os
,
"..."
);
P
.
String
(
t
.
P
os
,
"..."
);
default
:
P
.
Error
(
t
.
pos
,
t
.
f
orm
,
"type"
);
P
.
Error
(
t
.
Pos
,
t
.
F
orm
,
"type"
);
}
return
separator
;
...
...
@@ -544,90 +544,90 @@ func (P *Printer) Expr1(x *AST.Expr, prec1 int) {
return
;
// empty expression list
}
switch
x
.
t
ok
{
switch
x
.
T
ok
{
case
Scanner
.
TYPE
:
// type expr
P
.
Type
(
x
.
obj
.
t
yp
);
P
.
Type
(
x
.
Obj
.
T
yp
);
case
Scanner
.
IDENT
:
P
.
HtmlIdentifier
(
x
);
case
Scanner
.
INT
,
Scanner
.
STRING
,
Scanner
.
FLOAT
:
// literal
P
.
String
(
x
.
pos
,
x
.
obj
.
i
dent
);
P
.
String
(
x
.
Pos
,
x
.
Obj
.
I
dent
);
case
Scanner
.
FUNC
:
// function literal
P
.
String
(
x
.
p
os
,
"func"
);
P
.
Type
(
x
.
obj
.
t
yp
);
P
.
Block
(
0
,
x
.
obj
.
block
,
x
.
obj
.
e
nd
,
true
);
P
.
String
(
x
.
P
os
,
"func"
);
P
.
Type
(
x
.
Obj
.
T
yp
);
P
.
Block
(
0
,
x
.
Obj
.
Block
,
x
.
Obj
.
E
nd
,
true
);
P
.
newlines
=
0
;
case
Scanner
.
COMMA
:
// list
// (don't use binary expression printing because of different spacing)
P
.
Expr
(
x
.
x
);
P
.
String
(
x
.
p
os
,
","
);
P
.
Expr
(
x
.
X
);
P
.
String
(
x
.
P
os
,
","
);
P
.
separator
=
blank
;
P
.
state
=
inside_list
;
P
.
Expr
(
x
.
y
);
P
.
Expr
(
x
.
Y
);
case
Scanner
.
PERIOD
:
// selector or type guard
P
.
Expr1
(
x
.
x
,
Scanner
.
HighestPrec
);
P
.
String
(
x
.
p
os
,
"."
);
if
x
.
y
.
t
ok
==
Scanner
.
TYPE
{
P
.
Expr1
(
x
.
X
,
Scanner
.
HighestPrec
);
P
.
String
(
x
.
P
os
,
"."
);
if
x
.
Y
.
T
ok
==
Scanner
.
TYPE
{
P
.
String
(
0
,
"("
);
P
.
Expr
(
x
.
y
);
P
.
Expr
(
x
.
Y
);
P
.
String
(
0
,
")"
);
}
else
{
P
.
Expr1
(
x
.
y
,
Scanner
.
HighestPrec
);
P
.
Expr1
(
x
.
Y
,
Scanner
.
HighestPrec
);
}
case
Scanner
.
LBRACK
:
// index
P
.
Expr1
(
x
.
x
,
Scanner
.
HighestPrec
);
P
.
String
(
x
.
p
os
,
"["
);
P
.
Expr1
(
x
.
y
,
0
);
P
.
Expr1
(
x
.
X
,
Scanner
.
HighestPrec
);
P
.
String
(
x
.
P
os
,
"["
);
P
.
Expr1
(
x
.
Y
,
0
);
P
.
String
(
0
,
"]"
);
case
Scanner
.
LPAREN
:
// call
P
.
Expr1
(
x
.
x
,
Scanner
.
HighestPrec
);
P
.
String
(
x
.
p
os
,
"("
);
P
.
Expr
(
x
.
y
);
P
.
Expr1
(
x
.
X
,
Scanner
.
HighestPrec
);
P
.
String
(
x
.
P
os
,
"("
);
P
.
Expr
(
x
.
Y
);
P
.
String
(
0
,
")"
);
case
Scanner
.
LBRACE
:
// composite literal
P
.
Type
(
x
.
obj
.
t
yp
);
P
.
String
(
x
.
p
os
,
"{"
);
P
.
Expr
(
x
.
y
);
P
.
Type
(
x
.
Obj
.
T
yp
);
P
.
String
(
x
.
P
os
,
"{"
);
P
.
Expr
(
x
.
Y
);
P
.
String
(
0
,
"}"
);
default
:
// unary and binary expressions including ":" for pairs
prec
:=
Scanner
.
UnaryPrec
;
if
x
.
x
!=
nil
{
prec
=
Scanner
.
Precedence
(
x
.
t
ok
);
if
x
.
X
!=
nil
{
prec
=
Scanner
.
Precedence
(
x
.
T
ok
);
}
if
prec
<
prec1
{
P
.
String
(
0
,
"("
);
}
if
x
.
x
==
nil
{
if
x
.
X
==
nil
{
// unary expression
P
.
Token
(
x
.
pos
,
x
.
t
ok
);
if
x
.
t
ok
==
Scanner
.
RANGE
{
P
.
Token
(
x
.
Pos
,
x
.
T
ok
);
if
x
.
T
ok
==
Scanner
.
RANGE
{
P
.
separator
=
blank
;
}
}
else
{
// binary expression
P
.
Expr1
(
x
.
x
,
prec
);
P
.
Expr1
(
x
.
X
,
prec
);
P
.
separator
=
blank
;
P
.
Token
(
x
.
pos
,
x
.
t
ok
);
P
.
Token
(
x
.
Pos
,
x
.
T
ok
);
P
.
separator
=
blank
;
}
P
.
Expr1
(
x
.
y
,
prec
);
P
.
Expr1
(
x
.
Y
,
prec
);
if
prec
<
prec1
{
P
.
String
(
0
,
")"
);
}
...
...
@@ -676,32 +676,32 @@ func (P *Printer) Block(pos int, list *array.Array, end int, indent bool) {
func
(
P
*
Printer
)
ControlClause
(
s
*
AST
.
Stat
)
{
has_post
:=
s
.
tok
==
Scanner
.
FOR
&&
s
.
p
ost
!=
nil
;
// post also used by "if"
has_post
:=
s
.
Tok
==
Scanner
.
FOR
&&
s
.
P
ost
!=
nil
;
// post also used by "if"
P
.
separator
=
blank
;
if
s
.
i
nit
==
nil
&&
!
has_post
{
if
s
.
I
nit
==
nil
&&
!
has_post
{
// no semicolons required
if
s
.
e
xpr
!=
nil
{
P
.
Expr
(
s
.
e
xpr
);
if
s
.
E
xpr
!=
nil
{
P
.
Expr
(
s
.
E
xpr
);
}
}
else
{
// all semicolons required
// (they are not separators, print them explicitly)
if
s
.
i
nit
!=
nil
{
P
.
Stat
(
s
.
i
nit
);
if
s
.
I
nit
!=
nil
{
P
.
Stat
(
s
.
I
nit
);
P
.
separator
=
none
;
}
P
.
String
(
0
,
";"
);
P
.
separator
=
blank
;
if
s
.
e
xpr
!=
nil
{
P
.
Expr
(
s
.
e
xpr
);
if
s
.
E
xpr
!=
nil
{
P
.
Expr
(
s
.
E
xpr
);
P
.
separator
=
none
;
}
if
s
.
t
ok
==
Scanner
.
FOR
{
if
s
.
T
ok
==
Scanner
.
FOR
{
P
.
String
(
0
,
";"
);
P
.
separator
=
blank
;
if
has_post
{
P
.
Stat
(
s
.
p
ost
);
P
.
Stat
(
s
.
P
ost
);
}
}
}
...
...
@@ -712,76 +712,76 @@ func (P *Printer) ControlClause(s *AST.Stat) {
func
(
P
*
Printer
)
Declaration
(
d
*
AST
.
Decl
,
parenthesized
bool
);
func
(
P
*
Printer
)
Stat
(
s
*
AST
.
Stat
)
{
switch
s
.
t
ok
{
switch
s
.
T
ok
{
case
Scanner
.
EXPRSTAT
:
// expression statement
P
.
Expr
(
s
.
e
xpr
);
P
.
Expr
(
s
.
E
xpr
);
P
.
separator
=
semicolon
;
case
Scanner
.
COLON
:
// label declaration
P
.
indentation
--
;
P
.
Expr
(
s
.
e
xpr
);
P
.
Token
(
s
.
pos
,
s
.
t
ok
);
P
.
Expr
(
s
.
E
xpr
);
P
.
Token
(
s
.
Pos
,
s
.
T
ok
);
P
.
indentation
++
;
P
.
separator
=
none
;
case
Scanner
.
CONST
,
Scanner
.
TYPE
,
Scanner
.
VAR
:
// declaration
P
.
Declaration
(
s
.
d
ecl
,
false
);
P
.
Declaration
(
s
.
D
ecl
,
false
);
case
Scanner
.
INC
,
Scanner
.
DEC
:
P
.
Expr
(
s
.
e
xpr
);
P
.
Token
(
s
.
pos
,
s
.
t
ok
);
P
.
Expr
(
s
.
E
xpr
);
P
.
Token
(
s
.
Pos
,
s
.
T
ok
);
P
.
separator
=
semicolon
;
case
Scanner
.
LBRACE
:
// block
P
.
Block
(
s
.
pos
,
s
.
block
,
s
.
e
nd
,
true
);
P
.
Block
(
s
.
Pos
,
s
.
Block
,
s
.
E
nd
,
true
);
case
Scanner
.
IF
:
P
.
String
(
s
.
p
os
,
"if"
);
P
.
String
(
s
.
P
os
,
"if"
);
P
.
ControlClause
(
s
);
P
.
Block
(
0
,
s
.
block
,
s
.
e
nd
,
true
);
if
s
.
p
ost
!=
nil
{
P
.
Block
(
0
,
s
.
Block
,
s
.
E
nd
,
true
);
if
s
.
P
ost
!=
nil
{
P
.
separator
=
blank
;
P
.
String
(
0
,
"else"
);
P
.
separator
=
blank
;
P
.
Stat
(
s
.
p
ost
);
P
.
Stat
(
s
.
P
ost
);
}
case
Scanner
.
FOR
:
P
.
String
(
s
.
p
os
,
"for"
);
P
.
String
(
s
.
P
os
,
"for"
);
P
.
ControlClause
(
s
);
P
.
Block
(
0
,
s
.
block
,
s
.
e
nd
,
true
);
P
.
Block
(
0
,
s
.
Block
,
s
.
E
nd
,
true
);
case
Scanner
.
SWITCH
,
Scanner
.
SELECT
:
P
.
Token
(
s
.
pos
,
s
.
t
ok
);
P
.
Token
(
s
.
Pos
,
s
.
T
ok
);
P
.
ControlClause
(
s
);
P
.
Block
(
0
,
s
.
block
,
s
.
e
nd
,
false
);
P
.
Block
(
0
,
s
.
Block
,
s
.
E
nd
,
false
);
case
Scanner
.
CASE
,
Scanner
.
DEFAULT
:
P
.
Token
(
s
.
pos
,
s
.
t
ok
);
if
s
.
e
xpr
!=
nil
{
P
.
Token
(
s
.
Pos
,
s
.
T
ok
);
if
s
.
E
xpr
!=
nil
{
P
.
separator
=
blank
;
P
.
Expr
(
s
.
e
xpr
);
P
.
Expr
(
s
.
E
xpr
);
}
P
.
String
(
0
,
":"
);
P
.
indentation
++
;
P
.
StatementList
(
s
.
b
lock
);
P
.
StatementList
(
s
.
B
lock
);
P
.
indentation
--
;
P
.
newlines
=
1
;
case
Scanner
.
GO
,
Scanner
.
RETURN
,
Scanner
.
FALLTHROUGH
,
Scanner
.
BREAK
,
Scanner
.
CONTINUE
,
Scanner
.
GOTO
:
P
.
Token
(
s
.
pos
,
s
.
t
ok
);
if
s
.
e
xpr
!=
nil
{
P
.
Token
(
s
.
Pos
,
s
.
T
ok
);
if
s
.
E
xpr
!=
nil
{
P
.
separator
=
blank
;
P
.
Expr
(
s
.
e
xpr
);
P
.
Expr
(
s
.
E
xpr
);
}
P
.
separator
=
semicolon
;
default
:
P
.
Error
(
s
.
pos
,
s
.
t
ok
,
"stat"
);
P
.
Error
(
s
.
Pos
,
s
.
T
ok
,
"stat"
);
}
}
...
...
@@ -791,80 +791,80 @@ func (P *Printer) Stat(s *AST.Stat) {
func
(
P
*
Printer
)
Declaration
(
d
*
AST
.
Decl
,
parenthesized
bool
)
{
if
!
parenthesized
{
if
d
.
e
xported
{
P
.
String
(
d
.
p
os
,
"export"
);
if
d
.
E
xported
{
P
.
String
(
d
.
P
os
,
"export"
);
P
.
separator
=
blank
;
}
P
.
Token
(
d
.
pos
,
d
.
t
ok
);
P
.
Token
(
d
.
Pos
,
d
.
T
ok
);
P
.
separator
=
blank
;
}
if
d
.
tok
!=
Scanner
.
FUNC
&&
d
.
l
ist
!=
nil
{
if
d
.
Tok
!=
Scanner
.
FUNC
&&
d
.
L
ist
!=
nil
{
// group of parenthesized declarations
P
.
state
=
opening_scope
;
P
.
String
(
0
,
"("
);
if
d
.
l
ist
.
Len
()
>
0
{
if
d
.
L
ist
.
Len
()
>
0
{
P
.
newlines
=
1
;
for
i
:=
0
;
i
<
d
.
l
ist
.
Len
();
i
++
{
P
.
Declaration
(
d
.
l
ist
.
At
(
i
)
.
(
*
AST
.
Decl
),
true
);
for
i
:=
0
;
i
<
d
.
L
ist
.
Len
();
i
++
{
P
.
Declaration
(
d
.
L
ist
.
At
(
i
)
.
(
*
AST
.
Decl
),
true
);
P
.
separator
=
semicolon
;
P
.
newlines
=
1
;
}
}
P
.
state
=
closing_scope
;
P
.
String
(
d
.
e
nd
,
")"
);
P
.
String
(
d
.
E
nd
,
")"
);
}
else
{
// single declaration
switch
d
.
t
ok
{
switch
d
.
T
ok
{
case
Scanner
.
IMPORT
:
if
d
.
i
dent
!=
nil
{
P
.
Expr
(
d
.
i
dent
);
if
d
.
I
dent
!=
nil
{
P
.
Expr
(
d
.
I
dent
);
}
else
{
P
.
String
(
d
.
val
.
p
os
,
""
);
// flush pending ';' separator/newlines
P
.
String
(
d
.
Val
.
P
os
,
""
);
// flush pending ';' separator/newlines
}
P
.
separator
=
tab
;
P
.
Expr
(
d
.
v
al
);
P
.
Expr
(
d
.
V
al
);
P
.
separator
=
semicolon
;
case
Scanner
.
EXPORT
:
P
.
Expr
(
d
.
i
dent
);
P
.
Expr
(
d
.
I
dent
);
P
.
separator
=
semicolon
;
case
Scanner
.
TYPE
:
P
.
Expr
(
d
.
i
dent
);
P
.
Expr
(
d
.
I
dent
);
P
.
separator
=
blank
;
// TODO switch to tab? (but indentation problem with structs)
P
.
separator
=
P
.
Type
(
d
.
t
yp
);
P
.
separator
=
P
.
Type
(
d
.
T
yp
);
case
Scanner
.
CONST
,
Scanner
.
VAR
:
P
.
Expr
(
d
.
i
dent
);
if
d
.
t
yp
!=
nil
{
P
.
Expr
(
d
.
I
dent
);
if
d
.
T
yp
!=
nil
{
P
.
separator
=
blank
;
// TODO switch to tab? (indentation problem with structs)
P
.
separator
=
P
.
Type
(
d
.
t
yp
);
P
.
separator
=
P
.
Type
(
d
.
T
yp
);
}
if
d
.
v
al
!=
nil
{
if
d
.
V
al
!=
nil
{
P
.
separator
=
tab
;
P
.
String
(
0
,
"="
);
P
.
separator
=
blank
;
P
.
Expr
(
d
.
v
al
);
P
.
Expr
(
d
.
V
al
);
}
P
.
separator
=
semicolon
;
case
Scanner
.
FUNC
:
if
d
.
typ
.
k
ey
!=
nil
{
if
d
.
Typ
.
K
ey
!=
nil
{
// method: print receiver
P
.
Parameters
(
0
,
d
.
typ
.
key
.
l
ist
);
P
.
Parameters
(
0
,
d
.
Typ
.
Key
.
L
ist
);
P
.
separator
=
blank
;
}
P
.
Expr
(
d
.
i
dent
);
P
.
separator
=
P
.
Type
(
d
.
t
yp
);
if
d
.
l
ist
!=
nil
{
P
.
Expr
(
d
.
I
dent
);
P
.
separator
=
P
.
Type
(
d
.
T
yp
);
if
d
.
L
ist
!=
nil
{
P
.
separator
=
blank
;
P
.
Block
(
0
,
d
.
list
,
d
.
e
nd
,
true
);
P
.
Block
(
0
,
d
.
List
,
d
.
E
nd
,
true
);
}
default
:
P
.
Error
(
d
.
pos
,
d
.
t
ok
,
"decl"
);
P
.
Error
(
d
.
Pos
,
d
.
T
ok
,
"decl"
);
}
}
...
...
@@ -876,12 +876,12 @@ func (P *Printer) Declaration(d *AST.Decl, parenthesized bool) {
// Program
func
(
P
*
Printer
)
Program
(
p
*
AST
.
Program
)
{
P
.
String
(
p
.
p
os
,
"package"
);
P
.
String
(
p
.
P
os
,
"package"
);
P
.
separator
=
blank
;
P
.
Expr
(
p
.
i
dent
);
P
.
Expr
(
p
.
I
dent
);
P
.
newlines
=
1
;
for
i
:=
0
;
i
<
p
.
d
ecls
.
Len
();
i
++
{
P
.
Declaration
(
p
.
d
ecls
.
At
(
i
)
.
(
*
AST
.
Decl
),
false
);
for
i
:=
0
;
i
<
p
.
D
ecls
.
Len
();
i
++
{
P
.
Declaration
(
p
.
D
ecls
.
At
(
i
)
.
(
*
AST
.
Decl
),
false
);
}
P
.
newlines
=
1
;
}
...
...
@@ -898,10 +898,10 @@ export func Print(prog *AST.Program) {
padchar
=
'\t'
;
}
text
:=
tabwriter
.
New
(
os
.
Stdout
,
*
tabwidth
,
1
,
padchar
,
true
,
*
html
);
P
.
Init
(
text
,
prog
.
c
omments
);
P
.
Init
(
text
,
prog
.
C
omments
);
// TODO would be better to make the name of the src file be the title
P
.
HtmlPrologue
(
"package "
+
prog
.
ident
.
obj
.
i
dent
);
P
.
HtmlPrologue
(
"package "
+
prog
.
Ident
.
Obj
.
I
dent
);
P
.
Program
(
prog
);
P
.
HtmlEpilogue
();
...
...
usr/gri/pretty/scanner.go
View file @
2527bba9
...
...
@@ -4,10 +4,11 @@
package
Scanner
import
"utf8"
import
"unicode"
import
Utils
"utils"
import
(
"utf8"
;
"unicode"
;
"utils"
;
)
export
const
(
ILLEGAL
=
iota
;
...
...
@@ -75,7 +76,7 @@ export const (
PERIOD
;
// keywords
K
EYWORDS_BEG
;
K
eywords_beg
;
// do not export eventually
BREAK
;
CASE
;
CHAN
;
...
...
@@ -105,7 +106,7 @@ export const (
SWITCH
;
TYPE
;
VAR
;
K
EYWORDS_END
;
K
eywords_end
;
// do not export eventually
// AST use only
EXPRSTAT
;
...
...
@@ -243,13 +244,13 @@ export func Precedence(tok int) int {
}
var
K
eywords
map
[
string
]
int
;
var
k
eywords
map
[
string
]
int
;
func
init
()
{
K
eywords
=
make
(
map
[
string
]
int
);
for
i
:=
K
EYWORDS_BEG
+
1
;
i
<
KEYWORDS_END
;
i
++
{
K
eywords
[
TokenString
(
i
)]
=
i
;
k
eywords
=
make
(
map
[
string
]
int
);
for
i
:=
K
eywords_beg
+
1
;
i
<
Keywords_end
;
i
++
{
k
eywords
[
TokenString
(
i
)]
=
i
;
}
}
...
...
@@ -301,7 +302,7 @@ export type Scanner struct {
// Read the next Unicode char into S.ch.
// S.ch < 0 means end-of-file.
func
(
S
*
Scanner
)
N
ext
()
{
func
(
S
*
Scanner
)
n
ext
()
{
if
S
.
pos
<
len
(
S
.
src
)
{
// assume ascii
r
,
w
:=
int
(
S
.
src
[
S
.
pos
]),
1
;
...
...
@@ -333,7 +334,7 @@ func (S *Scanner) Error(pos int, msg string) {
}
func
(
S
*
Scanner
)
E
xpectNoErrors
()
{
func
(
S
*
Scanner
)
e
xpectNoErrors
()
{
// set the next expected error position to one after eof
// (the eof position is a legal error position!)
S
.
testpos
=
len
(
S
.
src
)
+
1
;
...
...
@@ -349,12 +350,12 @@ func (S *Scanner) Init(err ErrorHandler, src string, scan_comments, testmode boo
S
.
linepos
=
0
;
S
.
testmode
=
testmode
;
S
.
E
xpectNoErrors
();
// S.src must be set
S
.
Next
();
// S.E
xpectNoErrrors() must be called before
S
.
e
xpectNoErrors
();
// S.src must be set
S
.
next
();
// S.e
xpectNoErrrors() must be called before
}
func
C
harString
(
ch
int
)
string
{
func
c
harString
(
ch
int
)
string
{
s
:=
string
(
ch
);
switch
ch
{
case
'\a'
:
s
=
`\a`
;
...
...
@@ -371,15 +372,15 @@ func CharString(ch int) string {
}
func
(
S
*
Scanner
)
E
xpect
(
ch
int
)
{
func
(
S
*
Scanner
)
e
xpect
(
ch
int
)
{
if
S
.
ch
!=
ch
{
S
.
Error
(
S
.
chpos
,
"expected "
+
CharString
(
ch
)
+
", found "
+
C
harString
(
S
.
ch
));
S
.
Error
(
S
.
chpos
,
"expected "
+
charString
(
ch
)
+
", found "
+
c
harString
(
S
.
ch
));
}
S
.
N
ext
();
// make always progress
S
.
n
ext
();
// make always progress
}
func
(
S
*
Scanner
)
S
kipWhitespace
()
{
func
(
S
*
Scanner
)
s
kipWhitespace
()
{
for
{
switch
S
.
ch
{
case
'\t'
,
'\r'
,
' '
:
...
...
@@ -391,37 +392,37 @@ func (S *Scanner) SkipWhitespace() {
default
:
return
;
}
S
.
N
ext
();
S
.
n
ext
();
}
panic
(
"UNREACHABLE"
);
}
func
(
S
*
Scanner
)
S
canComment
()
string
{
func
(
S
*
Scanner
)
s
canComment
()
string
{
// first '/' already consumed
pos
:=
S
.
chpos
-
1
;
if
S
.
ch
==
'/'
{
//-style comment
S
.
N
ext
();
S
.
n
ext
();
for
S
.
ch
>=
0
{
S
.
N
ext
();
S
.
n
ext
();
if
S
.
ch
==
'\n'
{
// '\n' terminates comment but we do not include
// it in the comment (otherwise we don't see the
// start of a newline in
S
kipWhitespace()).
// start of a newline in
s
kipWhitespace()).
goto
exit
;
}
}
}
else
{
/*-style comment */
S
.
E
xpect
(
'*'
);
S
.
e
xpect
(
'*'
);
for
S
.
ch
>=
0
{
ch
:=
S
.
ch
;
S
.
N
ext
();
S
.
n
ext
();
if
ch
==
'*'
&&
S
.
ch
==
'/'
{
S
.
N
ext
();
S
.
n
ext
();
goto
exit
;
}
}
...
...
@@ -439,12 +440,12 @@ exit:
case
len
(
comment
)
>=
8
&&
comment
[
3
:
8
]
==
"ERROR"
:
// an error is expected at the next token position
oldpos
=
S
.
testpos
;
S
.
S
kipWhitespace
();
S
.
s
kipWhitespace
();
S
.
testpos
=
S
.
chpos
;
case
len
(
comment
)
>=
7
&&
comment
[
3
:
7
]
==
"SYNC"
:
// scanning/parsing synchronized again - no (follow-up) errors expected
oldpos
=
S
.
testpos
;
S
.
E
xpectNoErrors
();
S
.
e
xpectNoErrors
();
}
if
0
<=
oldpos
&&
oldpos
<=
len
(
S
.
src
)
{
...
...
@@ -457,15 +458,15 @@ exit:
}
func
(
S
*
Scanner
)
S
canIdentifier
()
(
tok
int
,
val
string
)
{
func
(
S
*
Scanner
)
s
canIdentifier
()
(
tok
int
,
val
string
)
{
pos
:=
S
.
chpos
;
for
is_letter
(
S
.
ch
)
||
digit_val
(
S
.
ch
)
<
10
{
S
.
N
ext
();
S
.
n
ext
();
}
val
=
S
.
src
[
pos
:
S
.
chpos
];
var
present
bool
;
tok
,
present
=
K
eywords
[
val
];
tok
,
present
=
k
eywords
[
val
];
if
!
present
{
tok
=
IDENT
;
}
...
...
@@ -474,34 +475,34 @@ func (S *Scanner) ScanIdentifier() (tok int, val string) {
}
func
(
S
*
Scanner
)
S
canMantissa
(
base
int
)
{
func
(
S
*
Scanner
)
s
canMantissa
(
base
int
)
{
for
digit_val
(
S
.
ch
)
<
base
{
S
.
N
ext
();
S
.
n
ext
();
}
}
func
(
S
*
Scanner
)
S
canNumber
(
seen_decimal_point
bool
)
(
tok
int
,
val
string
)
{
func
(
S
*
Scanner
)
s
canNumber
(
seen_decimal_point
bool
)
(
tok
int
,
val
string
)
{
pos
:=
S
.
chpos
;
tok
=
INT
;
if
seen_decimal_point
{
tok
=
FLOAT
;
pos
--
;
// '.' is one byte
S
.
S
canMantissa
(
10
);
S
.
s
canMantissa
(
10
);
goto
exponent
;
}
if
S
.
ch
==
'0'
{
// int or float
S
.
N
ext
();
S
.
n
ext
();
if
S
.
ch
==
'x'
||
S
.
ch
==
'X'
{
// hexadecimal int
S
.
N
ext
();
S
.
S
canMantissa
(
16
);
S
.
n
ext
();
S
.
s
canMantissa
(
16
);
}
else
{
// octal int or float
S
.
S
canMantissa
(
8
);
S
.
s
canMantissa
(
8
);
if
digit_val
(
S
.
ch
)
<
10
||
S
.
ch
==
'.'
||
S
.
ch
==
'e'
||
S
.
ch
==
'E'
{
// float
tok
=
FLOAT
;
...
...
@@ -514,24 +515,24 @@ func (S *Scanner) ScanNumber(seen_decimal_point bool) (tok int, val string) {
mantissa
:
// decimal int or float
S
.
S
canMantissa
(
10
);
S
.
s
canMantissa
(
10
);
if
S
.
ch
==
'.'
{
// float
tok
=
FLOAT
;
S
.
N
ext
();
S
.
S
canMantissa
(
10
)
S
.
n
ext
();
S
.
s
canMantissa
(
10
)
}
exponent
:
if
S
.
ch
==
'e'
||
S
.
ch
==
'E'
{
// float
tok
=
FLOAT
;
S
.
N
ext
();
S
.
n
ext
();
if
S
.
ch
==
'-'
||
S
.
ch
==
'+'
{
S
.
N
ext
();
S
.
n
ext
();
}
S
.
S
canMantissa
(
10
);
S
.
s
canMantissa
(
10
);
}
exit
:
...
...
@@ -539,9 +540,9 @@ exit:
}
func
(
S
*
Scanner
)
S
canDigits
(
n
int
,
base
int
)
{
func
(
S
*
Scanner
)
s
canDigits
(
n
int
,
base
int
)
{
for
digit_val
(
S
.
ch
)
<
base
{
S
.
N
ext
();
S
.
n
ext
();
n
--
;
}
if
n
>
0
{
...
...
@@ -550,30 +551,30 @@ func (S *Scanner) ScanDigits(n int, base int) {
}
func
(
S
*
Scanner
)
S
canEscape
(
quote
int
)
string
{
func
(
S
*
Scanner
)
s
canEscape
(
quote
int
)
string
{
// TODO: fix this routine
ch
:=
S
.
ch
;
pos
:=
S
.
chpos
;
S
.
N
ext
();
S
.
n
ext
();
switch
ch
{
case
'a'
,
'b'
,
'f'
,
'n'
,
'r'
,
't'
,
'v'
,
'\\'
:
return
string
(
ch
);
case
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
:
S
.
S
canDigits
(
3
-
1
,
8
);
// 1 char already read
S
.
s
canDigits
(
3
-
1
,
8
);
// 1 char already read
return
""
;
// TODO fix this
case
'x'
:
S
.
S
canDigits
(
2
,
16
);
S
.
s
canDigits
(
2
,
16
);
return
""
;
// TODO fix this
case
'u'
:
S
.
S
canDigits
(
4
,
16
);
S
.
s
canDigits
(
4
,
16
);
return
""
;
// TODO fix this
case
'U'
:
S
.
S
canDigits
(
8
,
16
);
S
.
s
canDigits
(
8
,
16
);
return
""
;
// TODO fix this
default
:
...
...
@@ -588,91 +589,91 @@ func (S *Scanner) ScanEscape(quote int) string {
}
func
(
S
*
Scanner
)
S
canChar
()
string
{
func
(
S
*
Scanner
)
s
canChar
()
string
{
// '\'' already consumed
pos
:=
S
.
chpos
-
1
;
ch
:=
S
.
ch
;
S
.
N
ext
();
S
.
n
ext
();
if
ch
==
'\\'
{
S
.
S
canEscape
(
'\'
'
);
S
.
s
canEscape
(
'\'
'
);
}
S
.
E
xpect
(
'\'
'
);
S
.
e
xpect
(
'\'
'
);
return
S
.
src
[
pos
:
S
.
chpos
];
}
func
(
S
*
Scanner
)
S
canString
()
string
{
func
(
S
*
Scanner
)
s
canString
()
string
{
// '"' already consumed
pos
:=
S
.
chpos
-
1
;
for
S
.
ch
!=
'"'
{
ch
:=
S
.
ch
;
S
.
N
ext
();
S
.
n
ext
();
if
ch
==
'\n'
||
ch
<
0
{
S
.
Error
(
pos
,
"string not terminated"
);
break
;
}
if
ch
==
'\\'
{
S
.
S
canEscape
(
'"'
);
S
.
s
canEscape
(
'"'
);
}
}
S
.
N
ext
();
S
.
n
ext
();
return
S
.
src
[
pos
:
S
.
chpos
];
}
func
(
S
*
Scanner
)
S
canRawString
()
string
{
func
(
S
*
Scanner
)
s
canRawString
()
string
{
// '`' already consumed
pos
:=
S
.
chpos
-
1
;
for
S
.
ch
!=
'`'
{
ch
:=
S
.
ch
;
S
.
N
ext
();
S
.
n
ext
();
if
ch
==
'\n'
||
ch
<
0
{
S
.
Error
(
pos
,
"string not terminated"
);
break
;
}
}
S
.
N
ext
();
S
.
n
ext
();
return
S
.
src
[
pos
:
S
.
chpos
];
}
func
(
S
*
Scanner
)
S
elect2
(
tok0
,
tok1
int
)
int
{
func
(
S
*
Scanner
)
s
elect2
(
tok0
,
tok1
int
)
int
{
if
S
.
ch
==
'='
{
S
.
N
ext
();
S
.
n
ext
();
return
tok1
;
}
return
tok0
;
}
func
(
S
*
Scanner
)
S
elect3
(
tok0
,
tok1
,
ch2
,
tok2
int
)
int
{
func
(
S
*
Scanner
)
s
elect3
(
tok0
,
tok1
,
ch2
,
tok2
int
)
int
{
if
S
.
ch
==
'='
{
S
.
N
ext
();
S
.
n
ext
();
return
tok1
;
}
if
S
.
ch
==
ch2
{
S
.
N
ext
();
S
.
n
ext
();
return
tok2
;
}
return
tok0
;
}
func
(
S
*
Scanner
)
S
elect4
(
tok0
,
tok1
,
ch2
,
tok2
,
tok3
int
)
int
{
func
(
S
*
Scanner
)
s
elect4
(
tok0
,
tok1
,
ch2
,
tok2
,
tok3
int
)
int
{
if
S
.
ch
==
'='
{
S
.
N
ext
();
S
.
n
ext
();
return
tok1
;
}
if
S
.
ch
==
ch2
{
S
.
N
ext
();
S
.
n
ext
();
if
S
.
ch
==
'='
{
S
.
N
ext
();
S
.
n
ext
();
return
tok3
;
}
return
tok2
;
...
...
@@ -683,29 +684,29 @@ func (S *Scanner) Select4(tok0, tok1, ch2, tok2, tok3 int) int {
func
(
S
*
Scanner
)
Scan
()
(
pos
,
tok
int
,
val
string
)
{
loop
:
S
.
S
kipWhitespace
();
S
.
s
kipWhitespace
();
pos
,
tok
=
S
.
chpos
,
ILLEGAL
;
switch
ch
:=
S
.
ch
;
{
case
is_letter
(
ch
)
:
tok
,
val
=
S
.
S
canIdentifier
();
case
digit_val
(
ch
)
<
10
:
tok
,
val
=
S
.
S
canNumber
(
false
);
case
is_letter
(
ch
)
:
tok
,
val
=
S
.
s
canIdentifier
();
case
digit_val
(
ch
)
<
10
:
tok
,
val
=
S
.
s
canNumber
(
false
);
default
:
S
.
N
ext
();
// always make progress
S
.
n
ext
();
// always make progress
switch
ch
{
case
-
1
:
tok
=
EOF
;
case
'\n'
:
tok
,
val
=
COMMENT
,
"
\n
"
;
case
'"'
:
tok
,
val
=
STRING
,
S
.
S
canString
();
case
'\'
'
:
tok
,
val
=
INT
,
S
.
S
canChar
();
case
'`'
:
tok
,
val
=
STRING
,
S
.
S
canRawString
();
case
':'
:
tok
=
S
.
S
elect2
(
COLON
,
DEFINE
);
case
'"'
:
tok
,
val
=
STRING
,
S
.
s
canString
();
case
'\'
'
:
tok
,
val
=
INT
,
S
.
s
canChar
();
case
'`'
:
tok
,
val
=
STRING
,
S
.
s
canRawString
();
case
':'
:
tok
=
S
.
s
elect2
(
COLON
,
DEFINE
);
case
'.'
:
if
digit_val
(
S
.
ch
)
<
10
{
tok
,
val
=
S
.
S
canNumber
(
true
);
tok
,
val
=
S
.
s
canNumber
(
true
);
}
else
if
S
.
ch
==
'.'
{
S
.
N
ext
();
S
.
n
ext
();
if
S
.
ch
==
'.'
{
S
.
N
ext
();
S
.
n
ext
();
tok
=
ELLIPSIS
;
}
}
else
{
...
...
@@ -719,34 +720,34 @@ loop:
case
']'
:
tok
=
RBRACK
;
case
'{'
:
tok
=
LBRACE
;
case
'}'
:
tok
=
RBRACE
;
case
'+'
:
tok
=
S
.
S
elect3
(
ADD
,
ADD_ASSIGN
,
'+'
,
INC
);
case
'-'
:
tok
=
S
.
S
elect3
(
SUB
,
SUB_ASSIGN
,
'-'
,
DEC
);
case
'*'
:
tok
=
S
.
S
elect2
(
MUL
,
MUL_ASSIGN
);
case
'+'
:
tok
=
S
.
s
elect3
(
ADD
,
ADD_ASSIGN
,
'+'
,
INC
);
case
'-'
:
tok
=
S
.
s
elect3
(
SUB
,
SUB_ASSIGN
,
'-'
,
DEC
);
case
'*'
:
tok
=
S
.
s
elect2
(
MUL
,
MUL_ASSIGN
);
case
'/'
:
if
S
.
ch
==
'/'
||
S
.
ch
==
'*'
{
tok
,
val
=
COMMENT
,
S
.
S
canComment
();
tok
,
val
=
COMMENT
,
S
.
s
canComment
();
if
!
S
.
scan_comments
{
goto
loop
;
}
}
else
{
tok
=
S
.
S
elect2
(
QUO
,
QUO_ASSIGN
);
tok
=
S
.
s
elect2
(
QUO
,
QUO_ASSIGN
);
}
case
'%'
:
tok
=
S
.
S
elect2
(
REM
,
REM_ASSIGN
);
case
'^'
:
tok
=
S
.
S
elect2
(
XOR
,
XOR_ASSIGN
);
case
'%'
:
tok
=
S
.
s
elect2
(
REM
,
REM_ASSIGN
);
case
'^'
:
tok
=
S
.
s
elect2
(
XOR
,
XOR_ASSIGN
);
case
'<'
:
if
S
.
ch
==
'-'
{
S
.
N
ext
();
S
.
n
ext
();
tok
=
ARROW
;
}
else
{
tok
=
S
.
S
elect4
(
LSS
,
LEQ
,
'<'
,
SHL
,
SHL_ASSIGN
);
tok
=
S
.
s
elect4
(
LSS
,
LEQ
,
'<'
,
SHL
,
SHL_ASSIGN
);
}
case
'>'
:
tok
=
S
.
S
elect4
(
GTR
,
GEQ
,
'>'
,
SHR
,
SHR_ASSIGN
);
case
'='
:
tok
=
S
.
S
elect2
(
ASSIGN
,
EQL
);
case
'!'
:
tok
=
S
.
S
elect2
(
NOT
,
NEQ
);
case
'&'
:
tok
=
S
.
S
elect3
(
AND
,
AND_ASSIGN
,
'&'
,
LAND
);
case
'|'
:
tok
=
S
.
S
elect3
(
OR
,
OR_ASSIGN
,
'|'
,
LOR
);
case
'>'
:
tok
=
S
.
s
elect4
(
GTR
,
GEQ
,
'>'
,
SHR
,
SHR_ASSIGN
);
case
'='
:
tok
=
S
.
s
elect2
(
ASSIGN
,
EQL
);
case
'!'
:
tok
=
S
.
s
elect2
(
NOT
,
NEQ
);
case
'&'
:
tok
=
S
.
s
elect3
(
AND
,
AND_ASSIGN
,
'&'
,
LAND
);
case
'|'
:
tok
=
S
.
s
elect3
(
OR
,
OR_ASSIGN
,
'|'
,
LOR
);
default
:
S
.
Error
(
pos
,
"illegal character "
+
C
harString
(
ch
));
S
.
Error
(
pos
,
"illegal character "
+
c
harString
(
ch
));
tok
=
ILLEGAL
;
}
}
...
...
@@ -756,9 +757,9 @@ loop:
export
type
Token
struct
{
p
os
int
;
t
ok
int
;
v
al
string
;
P
os
int
;
T
ok
int
;
V
al
string
;
}
...
...
@@ -767,9 +768,9 @@ func (S *Scanner) TokenStream() <-chan *Token {
go
func
(
S
*
Scanner
,
ch
chan
<-
*
Token
)
{
for
{
t
:=
new
(
Token
);
t
.
pos
,
t
.
tok
,
t
.
v
al
=
S
.
Scan
();
t
.
Pos
,
t
.
Tok
,
t
.
V
al
=
S
.
Scan
();
ch
<-
t
;
if
t
.
t
ok
==
EOF
{
if
t
.
T
ok
==
EOF
{
break
;
}
}
...
...
usr/gri/pretty/selftest0.go
View file @
2527bba9
...
...
@@ -4,7 +4,7 @@
package
main
type
Proto
struct
{
export
type
Proto
struct
{
a
int
"a tag"
;
b
,
c
,
d
*
Proto
"bcd"
"tag"
;
*
Proto
"proto tag"
...
...
usr/gri/pretty/selftest2.go
View file @
2527bba9
...
...
@@ -11,7 +11,7 @@ import (
)
const
/* enum1 */
(
export
const
/* enum1 */
(
EnumTag0
=
iota
;
EnumTag1
;
EnumTag2
;
...
...
@@ -32,10 +32,10 @@ const /* enum2 */ (
)
type
S
struct
{}
export
type
S
struct
{}
type
T
struct
{
export
type
T
struct
{
x
,
y
int
;
s
string
;
next_t
*
T
...
...
@@ -43,7 +43,7 @@ type T struct {
var
(
A
=
5
;
aa
=
5
;
u
,
v
,
w
int
=
0
,
0
,
0
;
foo
=
"foo"
;
fixed_array0
=
[
10
]
int
{};
...
...
@@ -54,7 +54,7 @@ var (
var
(
// Unicode identifiers
ä
,
ö
,
ü
,
Á
,
Ø
,
Å
,
ƒ
,
ß
int
;
ä
,
ö
,
ü
,
ƒ
,
ß
int
;
)
...
...
@@ -105,24 +105,24 @@ func f3(a *[]int, m map[string] int) {
}
println
(
"A3"
);
for
i
:
x
:=
range
a
{
for
i
,
x
:=
range
a
{
println
(
i
,
x
);
}
println
(
"M1"
);
for
i
range
m
{
for
i
:=
range
m
{
println
(
i
);
}
println
(
"M2"
);
for
i
,
x
range
m
{
for
i
,
x
:=
range
m
{
println
(
i
,
x
);
}
println
(
"M3"
);
var
i
string
;
var
x
int
;
for
i
:
x
=
range
m
{
for
i
,
x
=
range
m
{
println
(
i
,
x
);
}
}
...
...
usr/gri/pretty/test.sh
View file @
2527bba9
...
...
@@ -10,6 +10,7 @@ TMP3=test_tmp3.go
COUNT
=
0
count
()
{
#echo $1
let
COUNT
=
$COUNT
+1
let
M
=
$COUNT
%10
if
[
$M
==
0
]
;
then
...
...
@@ -25,7 +26,7 @@ apply1() {
# files with errors (skip them)
method1.go
|
selftest1.go
|
func3.go
|
bug014.go
|
bug029.go
|
bug032.go
|
bug050.go
|
\
bug068.go
|
bug088.go
|
bug083.go
|
bug106.go
|
bug125.go
|
bug126.go
)
;;
*
)
$1
$2
;
count
;;
*
)
$1
$2
;
count
$F
;;
esac
}
...
...
@@ -130,7 +131,7 @@ if [ $? != 0 ]; then
echo
"Error (selftest1): pretty -t selftest1.go"
exit
1
fi
count
count
selftest1.go
# run over all .go files
...
...
usr/gri/pretty/typechecker.go
View file @
2527bba9
...
...
@@ -11,13 +11,13 @@ import (
)
type
S
tate
struct
{
type
s
tate
struct
{
// setup
err
Scanner
.
ErrorHandler
;
}
func
(
s
*
S
tate
)
Init
(
err
Scanner
.
ErrorHandler
)
{
func
(
s
*
s
tate
)
Init
(
err
Scanner
.
ErrorHandler
)
{
s
.
err
=
err
;
}
...
...
@@ -42,27 +42,27 @@ func assert(pred bool) {
}
func
(
s
*
S
tate
)
Error
(
pos
int
,
msg
string
)
{
func
(
s
*
s
tate
)
Error
(
pos
int
,
msg
string
)
{
s
.
err
.
Error
(
pos
,
msg
);
}
// ----------------------------------------------------------------------------
func
(
s
*
S
tate
)
CheckType
()
{
func
(
s
*
s
tate
)
CheckType
()
{
}
func
(
s
*
S
tate
)
CheckDeclaration
(
d
*
AST
.
Decl
)
{
if
d
.
tok
!=
Scanner
.
FUNC
&&
d
.
l
ist
!=
nil
{
func
(
s
*
s
tate
)
CheckDeclaration
(
d
*
AST
.
Decl
)
{
if
d
.
Tok
!=
Scanner
.
FUNC
&&
d
.
L
ist
!=
nil
{
// group of parenthesized declarations
for
i
:=
0
;
i
<
d
.
l
ist
.
Len
();
i
++
{
s
.
CheckDeclaration
(
d
.
l
ist
.
At
(
i
)
.
(
*
AST
.
Decl
))
for
i
:=
0
;
i
<
d
.
L
ist
.
Len
();
i
++
{
s
.
CheckDeclaration
(
d
.
L
ist
.
At
(
i
)
.
(
*
AST
.
Decl
))
}
}
else
{
// single declaration
switch
d
.
t
ok
{
switch
d
.
T
ok
{
case
Scanner
.
IMPORT
:
case
Scanner
.
EXPORT
:
case
Scanner
.
CONST
:
...
...
@@ -76,9 +76,9 @@ func (s *State) CheckDeclaration(d *AST.Decl) {
}
func
(
s
*
S
tate
)
CheckProgram
(
p
*
AST
.
Program
)
{
for
i
:=
0
;
i
<
p
.
d
ecls
.
Len
();
i
++
{
s
.
CheckDeclaration
(
p
.
d
ecls
.
At
(
i
)
.
(
*
AST
.
Decl
));
func
(
s
*
s
tate
)
CheckProgram
(
p
*
AST
.
Program
)
{
for
i
:=
0
;
i
<
p
.
D
ecls
.
Len
();
i
++
{
s
.
CheckDeclaration
(
p
.
D
ecls
.
At
(
i
)
.
(
*
AST
.
Decl
));
}
}
...
...
@@ -86,7 +86,7 @@ func (s *State) CheckProgram(p *AST.Program) {
// ----------------------------------------------------------------------------
export
func
CheckProgram
(
err
Scanner
.
ErrorHandler
,
p
*
AST
.
Program
)
{
var
s
S
tate
;
var
s
s
tate
;
s
.
Init
(
err
);
s
.
CheckProgram
(
p
);
}
usr/gri/pretty/universe.go
View file @
2527bba9
...
...
@@ -11,113 +11,113 @@ import (
export
var
(
s
cope
*
AST
.
Scope
;
t
ypes
array
.
Array
;
S
cope
*
AST
.
Scope
;
T
ypes
array
.
Array
;
// internal types
v
oid_typ
,
b
ad_typ
,
n
il_typ
,
V
oid_typ
,
B
ad_typ
,
N
il_typ
,
// basic types
b
ool_typ
,
u
int8_typ
,
u
int16_typ
,
u
int32_typ
,
u
int64_typ
,
i
nt8_typ
,
i
nt16_typ
,
i
nt32_typ
,
i
nt64_typ
,
f
loat32_typ
,
f
loat64_typ
,
f
loat80_typ
,
s
tring_typ
,
i
nteger_typ
,
B
ool_typ
,
U
int8_typ
,
U
int16_typ
,
U
int32_typ
,
U
int64_typ
,
I
nt8_typ
,
I
nt16_typ
,
I
nt32_typ
,
I
nt64_typ
,
F
loat32_typ
,
F
loat64_typ
,
F
loat80_typ
,
S
tring_typ
,
I
nteger_typ
,
// convenience types
b
yte_typ
,
u
int_typ
,
i
nt_typ
,
f
loat_typ
,
u
intptr_typ
*
AST
.
Type
;
B
yte_typ
,
U
int_typ
,
I
nt_typ
,
F
loat_typ
,
U
intptr_typ
*
AST
.
Type
;
t
rue_obj
,
f
alse_obj
,
i
ota_obj
,
n
il_obj
*
AST
.
Object
;
T
rue_obj
,
F
alse_obj
,
I
ota_obj
,
N
il_obj
*
AST
.
Object
;
)
func
D
eclObj
(
kind
int
,
ident
string
,
typ
*
AST
.
Type
)
*
AST
.
Object
{
func
d
eclObj
(
kind
int
,
ident
string
,
typ
*
AST
.
Type
)
*
AST
.
Object
{
obj
:=
AST
.
NewObject
(
-
1
/* no source pos */
,
kind
,
ident
);
obj
.
t
yp
=
typ
;
if
kind
==
AST
.
TYPE
&&
typ
.
o
bj
==
nil
{
typ
.
o
bj
=
obj
;
// set primary type object
obj
.
T
yp
=
typ
;
if
kind
==
AST
.
TYPE
&&
typ
.
O
bj
==
nil
{
typ
.
O
bj
=
obj
;
// set primary type object
}
s
cope
.
Insert
(
obj
);
S
cope
.
Insert
(
obj
);
return
obj
}
func
D
eclType
(
form
int
,
ident
string
,
size
int
)
*
AST
.
Type
{
func
d
eclType
(
form
int
,
ident
string
,
size
int
)
*
AST
.
Type
{
typ
:=
AST
.
NewType
(
-
1
/* no source pos */
,
form
);
typ
.
s
ize
=
size
;
return
DeclObj
(
AST
.
TYPE
,
ident
,
typ
)
.
t
yp
;
typ
.
S
ize
=
size
;
return
declObj
(
AST
.
TYPE
,
ident
,
typ
)
.
T
yp
;
}
func
R
egister
(
typ
*
AST
.
Type
)
*
AST
.
Type
{
typ
.
ref
=
t
ypes
.
Len
();
t
ypes
.
Push
(
typ
);
func
r
egister
(
typ
*
AST
.
Type
)
*
AST
.
Type
{
typ
.
Ref
=
T
ypes
.
Len
();
T
ypes
.
Push
(
typ
);
return
typ
;
}
func
init
()
{
s
cope
=
AST
.
NewScope
(
nil
);
// universe has no parent
t
ypes
.
Init
(
32
);
S
cope
=
AST
.
NewScope
(
nil
);
// universe has no parent
T
ypes
.
Init
(
32
);
// Interal types
v
oid_typ
=
AST
.
NewType
(
-
1
/* no source pos */
,
AST
.
VOID
);
AST
.
Universe_void_typ
=
v
oid_typ
;
b
ad_typ
=
AST
.
NewType
(
-
1
/* no source pos */
,
AST
.
BADTYPE
);
n
il_typ
=
AST
.
NewType
(
-
1
/* no source pos */
,
AST
.
NIL
);
V
oid_typ
=
AST
.
NewType
(
-
1
/* no source pos */
,
AST
.
VOID
);
AST
.
Universe_void_typ
=
V
oid_typ
;
B
ad_typ
=
AST
.
NewType
(
-
1
/* no source pos */
,
AST
.
BADTYPE
);
N
il_typ
=
AST
.
NewType
(
-
1
/* no source pos */
,
AST
.
NIL
);
// Basic types
bool_typ
=
Register
(
D
eclType
(
AST
.
BOOL
,
"bool"
,
1
));
uint8_typ
=
Register
(
D
eclType
(
AST
.
UINT
,
"uint8"
,
1
));
uint16_typ
=
Register
(
D
eclType
(
AST
.
UINT
,
"uint16"
,
2
));
uint32_typ
=
Register
(
D
eclType
(
AST
.
UINT
,
"uint32"
,
4
));
uint64_typ
=
Register
(
D
eclType
(
AST
.
UINT
,
"uint64"
,
8
));
int8_typ
=
Register
(
D
eclType
(
AST
.
INT
,
"int8"
,
1
));
int16_typ
=
Register
(
D
eclType
(
AST
.
INT
,
"int16"
,
2
));
int32_typ
=
Register
(
D
eclType
(
AST
.
INT
,
"int32"
,
4
));
int64_typ
=
Register
(
D
eclType
(
AST
.
INT
,
"int64"
,
8
));
float32_typ
=
Register
(
D
eclType
(
AST
.
FLOAT
,
"float32"
,
4
));
float64_typ
=
Register
(
D
eclType
(
AST
.
FLOAT
,
"float64"
,
8
));
float80_typ
=
Register
(
D
eclType
(
AST
.
FLOAT
,
"float80"
,
10
));
string_typ
=
Register
(
D
eclType
(
AST
.
STRING
,
"string"
,
8
));
integer_typ
=
Register
(
D
eclType
(
AST
.
INTEGER
,
"integer"
,
8
));
Bool_typ
=
register
(
d
eclType
(
AST
.
BOOL
,
"bool"
,
1
));
Uint8_typ
=
register
(
d
eclType
(
AST
.
UINT
,
"uint8"
,
1
));
Uint16_typ
=
register
(
d
eclType
(
AST
.
UINT
,
"uint16"
,
2
));
Uint32_typ
=
register
(
d
eclType
(
AST
.
UINT
,
"uint32"
,
4
));
Uint64_typ
=
register
(
d
eclType
(
AST
.
UINT
,
"uint64"
,
8
));
Int8_typ
=
register
(
d
eclType
(
AST
.
INT
,
"int8"
,
1
));
Int16_typ
=
register
(
d
eclType
(
AST
.
INT
,
"int16"
,
2
));
Int32_typ
=
register
(
d
eclType
(
AST
.
INT
,
"int32"
,
4
));
Int64_typ
=
register
(
d
eclType
(
AST
.
INT
,
"int64"
,
8
));
Float32_typ
=
register
(
d
eclType
(
AST
.
FLOAT
,
"float32"
,
4
));
Float64_typ
=
register
(
d
eclType
(
AST
.
FLOAT
,
"float64"
,
8
));
Float80_typ
=
register
(
d
eclType
(
AST
.
FLOAT
,
"float80"
,
10
));
String_typ
=
register
(
d
eclType
(
AST
.
STRING
,
"string"
,
8
));
Integer_typ
=
register
(
d
eclType
(
AST
.
INTEGER
,
"integer"
,
8
));
// All but 'byte' should be platform-dependent, eventually.
byte_typ
=
Register
(
D
eclType
(
AST
.
UINT
,
"byte"
,
1
));
uint_typ
=
Register
(
D
eclType
(
AST
.
UINT
,
"uint"
,
4
));
int_typ
=
Register
(
D
eclType
(
AST
.
INT
,
"int"
,
4
));
float_typ
=
Register
(
D
eclType
(
AST
.
FLOAT
,
"float"
,
4
));
uintptr_typ
=
Register
(
D
eclType
(
AST
.
UINT
,
"uintptr"
,
8
));
Byte_typ
=
register
(
d
eclType
(
AST
.
UINT
,
"byte"
,
1
));
Uint_typ
=
register
(
d
eclType
(
AST
.
UINT
,
"uint"
,
4
));
Int_typ
=
register
(
d
eclType
(
AST
.
INT
,
"int"
,
4
));
Float_typ
=
register
(
d
eclType
(
AST
.
FLOAT
,
"float"
,
4
));
Uintptr_typ
=
register
(
d
eclType
(
AST
.
UINT
,
"uintptr"
,
8
));
// Predeclared constants
true_obj
=
DeclObj
(
AST
.
CONST
,
"true"
,
b
ool_typ
);
false_obj
=
DeclObj
(
AST
.
CONST
,
"false"
,
b
ool_typ
);
iota_obj
=
DeclObj
(
AST
.
CONST
,
"iota"
,
i
nt_typ
);
nil_obj
=
DeclObj
(
AST
.
CONST
,
"nil"
,
n
il_typ
);
True_obj
=
declObj
(
AST
.
CONST
,
"true"
,
B
ool_typ
);
False_obj
=
declObj
(
AST
.
CONST
,
"false"
,
B
ool_typ
);
Iota_obj
=
declObj
(
AST
.
CONST
,
"iota"
,
I
nt_typ
);
Nil_obj
=
declObj
(
AST
.
CONST
,
"nil"
,
N
il_typ
);
// Builtin functions
DeclObj
(
AST
.
BUILTIN
,
"len"
,
v
oid_typ
);
DeclObj
(
AST
.
BUILTIN
,
"new"
,
v
oid_typ
);
DeclObj
(
AST
.
BUILTIN
,
"panic"
,
v
oid_typ
);
DeclObj
(
AST
.
BUILTIN
,
"print"
,
v
oid_typ
);
declObj
(
AST
.
BUILTIN
,
"len"
,
V
oid_typ
);
declObj
(
AST
.
BUILTIN
,
"new"
,
V
oid_typ
);
declObj
(
AST
.
BUILTIN
,
"panic"
,
V
oid_typ
);
declObj
(
AST
.
BUILTIN
,
"print"
,
V
oid_typ
);
// scope.Print();
}
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