mirror of
https://github.com/golang/go
synced 2024-11-22 05:54:40 -07:00
Preparation for moving scanner into a lib:
- separated out token definition from scanner - cleaned up token and scanner implementation - added comments to exported interfaces R=r OCL=25665 CL=25665
This commit is contained in:
parent
337ce2220f
commit
77567265a8
@ -32,21 +32,21 @@ gds.6: utils.6 platform.6 compilation.6 printer.6
|
|||||||
|
|
||||||
pretty.6: platform.6 printer.6 compilation.6
|
pretty.6: platform.6 printer.6 compilation.6
|
||||||
|
|
||||||
compilation.6: platform.6 scanner.6 parser.6 ast.6 typechecker.6
|
compilation.6: platform.6 token.6 scanner.6 parser.6 ast.6 typechecker.6
|
||||||
|
|
||||||
typechecker.6: ast.6 scanner.6
|
typechecker.6: ast.6 token.6
|
||||||
|
|
||||||
scanner.6: utils.6
|
scanner.6: token.6 utils.6
|
||||||
|
|
||||||
ast.6: scanner.6 symboltable.6
|
ast.6: token.6 symboltable.6
|
||||||
|
|
||||||
symboltable.6:
|
symboltable.6:
|
||||||
|
|
||||||
parser.6: scanner.6 ast.6 symboltable.6
|
parser.6: token.6 scanner.6 ast.6 symboltable.6
|
||||||
|
|
||||||
platform.6: utils.6
|
platform.6: utils.6
|
||||||
|
|
||||||
printer.6: utils.6 scanner.6 ast.6 symboltable.6
|
printer.6: utils.6 token.6 ast.6 symboltable.6
|
||||||
|
|
||||||
%.6: %.go
|
%.6: %.go
|
||||||
$(G) $(F) $<
|
$(G) $(F) $<
|
||||||
|
@ -6,7 +6,7 @@ package AST
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"vector";
|
"vector";
|
||||||
Scanner "scanner";
|
"token";
|
||||||
SymbolTable "symboltable";
|
SymbolTable "symboltable";
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -259,7 +259,7 @@ func ExprLen(x Expr) int {
|
|||||||
}
|
}
|
||||||
n := 1;
|
n := 1;
|
||||||
for {
|
for {
|
||||||
if p, ok := x.(*BinaryExpr); ok && p.Tok == Scanner.COMMA {
|
if p, ok := x.(*BinaryExpr); ok && p.Tok == token.COMMA {
|
||||||
n++;
|
n++;
|
||||||
x = p.Y;
|
x = p.Y;
|
||||||
} else {
|
} else {
|
||||||
@ -272,10 +272,10 @@ func ExprLen(x Expr) int {
|
|||||||
|
|
||||||
func ExprAt(x Expr, i int) Expr {
|
func ExprAt(x Expr, i int) Expr {
|
||||||
for j := 0; j < i; j++ {
|
for j := 0; j < i; j++ {
|
||||||
assert(x.(*BinaryExpr).Tok == Scanner.COMMA);
|
assert(x.(*BinaryExpr).Tok == token.COMMA);
|
||||||
x = x.(*BinaryExpr).Y;
|
x = x.(*BinaryExpr).Y;
|
||||||
}
|
}
|
||||||
if t, is_binary := x.(*BinaryExpr); is_binary && t.Tok == Scanner.COMMA {
|
if t, is_binary := x.(*BinaryExpr); is_binary && t.Tok == token.COMMA {
|
||||||
x = t.X;
|
x = t.X;
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
@ -298,7 +298,7 @@ type Block struct {
|
|||||||
|
|
||||||
|
|
||||||
func NewBlock(pos, tok int) *Block {
|
func NewBlock(pos, tok int) *Block {
|
||||||
assert(tok == Scanner.LBRACE || tok == Scanner.COLON);
|
assert(tok == token.LBRACE || tok == token.COLON);
|
||||||
b := new(Block);
|
b := new(Block);
|
||||||
b.Pos, b.Tok, b.List = pos, tok, vector.New(0);
|
b.Pos, b.Tok, b.List = pos, tok, vector.New(0);
|
||||||
return b;
|
return b;
|
||||||
@ -509,7 +509,7 @@ func NewComment(pos int, text string) *Comment {
|
|||||||
|
|
||||||
|
|
||||||
type Program struct {
|
type Program struct {
|
||||||
Pos int; // tok is Scanner.PACKAGE
|
Pos int; // tok is token.PACKAGE
|
||||||
Ident Expr;
|
Ident Expr;
|
||||||
Decls []Decl;
|
Decls []Decl;
|
||||||
Comments *vector.Vector;
|
Comments *vector.Vector;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@ import (
|
|||||||
"flag";
|
"flag";
|
||||||
"fmt";
|
"fmt";
|
||||||
Utils "utils";
|
Utils "utils";
|
||||||
Scanner "scanner";
|
"token";
|
||||||
AST "ast";
|
AST "ast";
|
||||||
SymbolTable "symboltable";
|
SymbolTable "symboltable";
|
||||||
)
|
)
|
||||||
@ -136,7 +136,7 @@ func (P *Printer) Init(text io.Write, html bool, comments *vector.Vector) {
|
|||||||
// formatting parameters & semantic state initialized correctly by default
|
// formatting parameters & semantic state initialized correctly by default
|
||||||
|
|
||||||
// expression precedence
|
// expression precedence
|
||||||
P.prec = Scanner.LowestPrec;
|
P.prec = token.LowestPrec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -374,13 +374,13 @@ func (P *Printer) String(pos int, s string) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) Token(pos int, tok int) {
|
func (P *Printer) Token(pos int, tok int) {
|
||||||
P.String(pos, Scanner.TokenString(tok));
|
P.String(pos, token.TokenString(tok));
|
||||||
//P.TaggedString(pos, "<b>", Scanner.TokenString(tok), "</b>");
|
//P.TaggedString(pos, "<b>", token.TokenString(tok), "</b>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) Error(pos int, tok int, msg string) {
|
func (P *Printer) Error(pos int, tok int, msg string) {
|
||||||
fmt.Printf("\ninternal printing error: pos = %d, tok = %s, %s\n", pos, Scanner.TokenString(tok), msg);
|
fmt.Printf("\ninternal printing error: pos = %d, tok = %s, %s\n", pos, token.TokenString(tok), msg);
|
||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,7 +456,7 @@ func (P *Printer) Expr(x AST.Expr)
|
|||||||
func (P *Printer) Idents(list []*AST.Ident) {
|
func (P *Printer) Idents(list []*AST.Ident) {
|
||||||
for i, x := range list {
|
for i, x := range list {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
P.Token(0, Scanner.COMMA);
|
P.Token(0, token.COMMA);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.state = inside_list;
|
P.state = inside_list;
|
||||||
}
|
}
|
||||||
@ -466,7 +466,7 @@ func (P *Printer) Idents(list []*AST.Ident) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) Parameters(list []*AST.Field) {
|
func (P *Printer) Parameters(list []*AST.Field) {
|
||||||
P.Token(0, Scanner.LPAREN);
|
P.Token(0, token.LPAREN);
|
||||||
if len(list) > 0 {
|
if len(list) > 0 {
|
||||||
for i, par := range list {
|
for i, par := range list {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
@ -479,7 +479,7 @@ func (P *Printer) Parameters(list []*AST.Field) {
|
|||||||
P.Expr(par.Typ);
|
P.Expr(par.Typ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P.Token(0, Scanner.RPAREN);
|
P.Token(0, token.RPAREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ func (P *Printer) Signature(sig *AST.Signature) {
|
|||||||
func (P *Printer) Fields(list []*AST.Field, end int, is_interface bool) {
|
func (P *Printer) Fields(list []*AST.Field, end int, is_interface bool) {
|
||||||
P.state = opening_scope;
|
P.state = opening_scope;
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Token(0, Scanner.LBRACE);
|
P.Token(0, token.LBRACE);
|
||||||
|
|
||||||
if len(list) > 0 {
|
if len(list) > 0 {
|
||||||
P.newlines = 1;
|
P.newlines = 1;
|
||||||
@ -539,7 +539,7 @@ func (P *Printer) Fields(list []*AST.Field, end int, is_interface bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
P.state = closing_scope;
|
P.state = closing_scope;
|
||||||
P.Token(end, Scanner.RBRACE);
|
P.Token(end, token.RBRACE);
|
||||||
P.opt_semi = true;
|
P.opt_semi = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,17 +562,17 @@ func (P *Printer) DoIdent(x *AST.Ident) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoBinaryExpr(x *AST.BinaryExpr) {
|
func (P *Printer) DoBinaryExpr(x *AST.BinaryExpr) {
|
||||||
if x.Tok == Scanner.COMMA {
|
if x.Tok == token.COMMA {
|
||||||
// (don't use binary expression printing because of different spacing)
|
// (don't use binary expression printing because of different spacing)
|
||||||
P.Expr(x.X);
|
P.Expr(x.X);
|
||||||
P.Token(x.Pos_, Scanner.COMMA);
|
P.Token(x.Pos_, token.COMMA);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.state = inside_list;
|
P.state = inside_list;
|
||||||
P.Expr(x.Y);
|
P.Expr(x.Y);
|
||||||
} else {
|
} else {
|
||||||
prec := Scanner.Precedence(x.Tok);
|
prec := token.Precedence(x.Tok);
|
||||||
if prec < P.prec {
|
if prec < P.prec {
|
||||||
P.Token(0, Scanner.LPAREN);
|
P.Token(0, token.LPAREN);
|
||||||
}
|
}
|
||||||
P.Expr1(x.X, prec);
|
P.Expr1(x.X, prec);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
@ -580,24 +580,24 @@ func (P *Printer) DoBinaryExpr(x *AST.BinaryExpr) {
|
|||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Expr1(x.Y, prec);
|
P.Expr1(x.Y, prec);
|
||||||
if prec < P.prec {
|
if prec < P.prec {
|
||||||
P.Token(0, Scanner.RPAREN);
|
P.Token(0, token.RPAREN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoUnaryExpr(x *AST.UnaryExpr) {
|
func (P *Printer) DoUnaryExpr(x *AST.UnaryExpr) {
|
||||||
prec := Scanner.UnaryPrec;
|
prec := token.UnaryPrec;
|
||||||
if prec < P.prec {
|
if prec < P.prec {
|
||||||
P.Token(0, Scanner.LPAREN);
|
P.Token(0, token.LPAREN);
|
||||||
}
|
}
|
||||||
P.Token(x.Pos_, x.Tok);
|
P.Token(x.Pos_, x.Tok);
|
||||||
if x.Tok == Scanner.RANGE {
|
if x.Tok == token.RANGE {
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
}
|
}
|
||||||
P.Expr1(x.X, prec);
|
P.Expr1(x.X, prec);
|
||||||
if prec < P.prec {
|
if prec < P.prec {
|
||||||
P.Token(0, Scanner.RPAREN);
|
P.Token(0, token.RPAREN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,7 +608,7 @@ func (P *Printer) DoBasicLit(x *AST.BasicLit) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoFunctionLit(x *AST.FunctionLit) {
|
func (P *Printer) DoFunctionLit(x *AST.FunctionLit) {
|
||||||
P.Token(x.Pos_, Scanner.FUNC);
|
P.Token(x.Pos_, token.FUNC);
|
||||||
P.Signature(x.Typ);
|
P.Signature(x.Typ);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Block(x.Body, true);
|
P.Block(x.Body, true);
|
||||||
@ -617,64 +617,64 @@ func (P *Printer) DoFunctionLit(x *AST.FunctionLit) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoGroup(x *AST.Group) {
|
func (P *Printer) DoGroup(x *AST.Group) {
|
||||||
P.Token(x.Pos_, Scanner.LPAREN);
|
P.Token(x.Pos_, token.LPAREN);
|
||||||
P.Expr(x.X);
|
P.Expr(x.X);
|
||||||
P.Token(0, Scanner.RPAREN);
|
P.Token(0, token.RPAREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoSelector(x *AST.Selector) {
|
func (P *Printer) DoSelector(x *AST.Selector) {
|
||||||
P.Expr1(x.X, Scanner.HighestPrec);
|
P.Expr1(x.X, token.HighestPrec);
|
||||||
P.Token(x.Pos_, Scanner.PERIOD);
|
P.Token(x.Pos_, token.PERIOD);
|
||||||
P.Expr1(x.Sel, Scanner.HighestPrec);
|
P.Expr1(x.Sel, token.HighestPrec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoTypeGuard(x *AST.TypeGuard) {
|
func (P *Printer) DoTypeGuard(x *AST.TypeGuard) {
|
||||||
P.Expr1(x.X, Scanner.HighestPrec);
|
P.Expr1(x.X, token.HighestPrec);
|
||||||
P.Token(x.Pos_, Scanner.PERIOD);
|
P.Token(x.Pos_, token.PERIOD);
|
||||||
P.Token(0, Scanner.LPAREN);
|
P.Token(0, token.LPAREN);
|
||||||
P.Expr(x.Typ);
|
P.Expr(x.Typ);
|
||||||
P.Token(0, Scanner.RPAREN);
|
P.Token(0, token.RPAREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoIndex(x *AST.Index) {
|
func (P *Printer) DoIndex(x *AST.Index) {
|
||||||
P.Expr1(x.X, Scanner.HighestPrec);
|
P.Expr1(x.X, token.HighestPrec);
|
||||||
P.Token(x.Pos_, Scanner.LBRACK);
|
P.Token(x.Pos_, token.LBRACK);
|
||||||
P.Expr1(x.I, 0);
|
P.Expr1(x.I, 0);
|
||||||
P.Token(0, Scanner.RBRACK);
|
P.Token(0, token.RBRACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoCall(x *AST.Call) {
|
func (P *Printer) DoCall(x *AST.Call) {
|
||||||
P.Expr1(x.F, Scanner.HighestPrec);
|
P.Expr1(x.F, token.HighestPrec);
|
||||||
P.Token(x.Pos_, x.Tok);
|
P.Token(x.Pos_, x.Tok);
|
||||||
P.Expr(x.Args);
|
P.Expr(x.Args);
|
||||||
switch x.Tok {
|
switch x.Tok {
|
||||||
case Scanner.LPAREN: P.Token(0, Scanner.RPAREN);
|
case token.LPAREN: P.Token(0, token.RPAREN);
|
||||||
case Scanner.LBRACE: P.Token(0, Scanner.RBRACE);
|
case token.LBRACE: P.Token(0, token.RBRACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoEllipsis(x *AST.Ellipsis) {
|
func (P *Printer) DoEllipsis(x *AST.Ellipsis) {
|
||||||
P.Token(x.Pos_, Scanner.ELLIPSIS);
|
P.Token(x.Pos_, token.ELLIPSIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoArrayType(x *AST.ArrayType) {
|
func (P *Printer) DoArrayType(x *AST.ArrayType) {
|
||||||
P.Token(x.Pos_, Scanner.LBRACK);
|
P.Token(x.Pos_, token.LBRACK);
|
||||||
if x.Len != nil {
|
if x.Len != nil {
|
||||||
P.Expr(x.Len);
|
P.Expr(x.Len);
|
||||||
}
|
}
|
||||||
P.Token(0, Scanner.RBRACK);
|
P.Token(0, token.RBRACK);
|
||||||
P.Expr(x.Elt);
|
P.Expr(x.Elt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoStructType(x *AST.StructType) {
|
func (P *Printer) DoStructType(x *AST.StructType) {
|
||||||
P.Token(x.Pos_, Scanner.STRUCT);
|
P.Token(x.Pos_, token.STRUCT);
|
||||||
if x.End > 0 {
|
if x.End > 0 {
|
||||||
P.Fields(x.Fields, x.End, false);
|
P.Fields(x.Fields, x.End, false);
|
||||||
}
|
}
|
||||||
@ -682,19 +682,19 @@ func (P *Printer) DoStructType(x *AST.StructType) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoPointerType(x *AST.PointerType) {
|
func (P *Printer) DoPointerType(x *AST.PointerType) {
|
||||||
P.Token(x.Pos_, Scanner.MUL);
|
P.Token(x.Pos_, token.MUL);
|
||||||
P.Expr(x.Base);
|
P.Expr(x.Base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoFunctionType(x *AST.FunctionType) {
|
func (P *Printer) DoFunctionType(x *AST.FunctionType) {
|
||||||
P.Token(x.Pos_, Scanner.FUNC);
|
P.Token(x.Pos_, token.FUNC);
|
||||||
P.Signature(x.Sig);
|
P.Signature(x.Sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoInterfaceType(x *AST.InterfaceType) {
|
func (P *Printer) DoInterfaceType(x *AST.InterfaceType) {
|
||||||
P.Token(x.Pos_, Scanner.INTERFACE);
|
P.Token(x.Pos_, token.INTERFACE);
|
||||||
if x.End > 0 {
|
if x.End > 0 {
|
||||||
P.Fields(x.Methods, x.End, true);
|
P.Fields(x.Methods, x.End, true);
|
||||||
}
|
}
|
||||||
@ -707,11 +707,11 @@ func (P *Printer) DoSliceType(x *AST.SliceType) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoMapType(x *AST.MapType) {
|
func (P *Printer) DoMapType(x *AST.MapType) {
|
||||||
P.Token(x.Pos_, Scanner.MAP);
|
P.Token(x.Pos_, token.MAP);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Token(0, Scanner.LBRACK);
|
P.Token(0, token.LBRACK);
|
||||||
P.Expr(x.Key);
|
P.Expr(x.Key);
|
||||||
P.Token(0, Scanner.RBRACK);
|
P.Token(0, token.RBRACK);
|
||||||
P.Expr(x.Val);
|
P.Expr(x.Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,14 +719,14 @@ func (P *Printer) DoMapType(x *AST.MapType) {
|
|||||||
func (P *Printer) DoChannelType(x *AST.ChannelType) {
|
func (P *Printer) DoChannelType(x *AST.ChannelType) {
|
||||||
switch x.Mode {
|
switch x.Mode {
|
||||||
case AST.FULL:
|
case AST.FULL:
|
||||||
P.Token(x.Pos_, Scanner.CHAN);
|
P.Token(x.Pos_, token.CHAN);
|
||||||
case AST.RECV:
|
case AST.RECV:
|
||||||
P.Token(x.Pos_, Scanner.ARROW);
|
P.Token(x.Pos_, token.ARROW);
|
||||||
P.Token(0, Scanner.CHAN);
|
P.Token(0, token.CHAN);
|
||||||
case AST.SEND:
|
case AST.SEND:
|
||||||
P.Token(x.Pos_, Scanner.CHAN);
|
P.Token(x.Pos_, token.CHAN);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Token(0, Scanner.ARROW);
|
P.Token(0, token.ARROW);
|
||||||
}
|
}
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Expr(x.Val);
|
P.Expr(x.Val);
|
||||||
@ -746,7 +746,7 @@ func (P *Printer) Expr1(x AST.Expr, prec1 int) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) Expr(x AST.Expr) {
|
func (P *Printer) Expr(x AST.Expr) {
|
||||||
P.Expr1(x, Scanner.LowestPrec);
|
P.Expr1(x, token.LowestPrec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -789,8 +789,8 @@ func (P *Printer) Block(b *AST.Block, indent bool) {
|
|||||||
P.separator = none;
|
P.separator = none;
|
||||||
}
|
}
|
||||||
P.state = closing_scope;
|
P.state = closing_scope;
|
||||||
if b.Tok == Scanner.LBRACE {
|
if b.Tok == token.LBRACE {
|
||||||
P.Token(b.End, Scanner.RBRACE);
|
P.Token(b.End, token.RBRACE);
|
||||||
P.opt_semi = true;
|
P.opt_semi = true;
|
||||||
} else {
|
} else {
|
||||||
P.String(0, ""); // process closing_scope state transition!
|
P.String(0, ""); // process closing_scope state transition!
|
||||||
@ -808,7 +808,7 @@ func (P *Printer) DoBadStat(s *AST.BadStat) {
|
|||||||
func (P *Printer) DoLabelDecl(s *AST.LabelDecl) {
|
func (P *Printer) DoLabelDecl(s *AST.LabelDecl) {
|
||||||
P.indentation--;
|
P.indentation--;
|
||||||
P.Expr(s.Label);
|
P.Expr(s.Label);
|
||||||
P.Token(s.Pos, Scanner.COLON);
|
P.Token(s.Pos, token.COLON);
|
||||||
// TODO not quite correct:
|
// TODO not quite correct:
|
||||||
// - we must not print this optional semicolon, as it may invalidate code.
|
// - we must not print this optional semicolon, as it may invalidate code.
|
||||||
// - this will change once the AST reflects the LabelStatement change
|
// - this will change once the AST reflects the LabelStatement change
|
||||||
@ -824,12 +824,12 @@ func (P *Printer) DoDeclarationStat(s *AST.DeclarationStat) {
|
|||||||
|
|
||||||
func (P *Printer) DoExpressionStat(s *AST.ExpressionStat) {
|
func (P *Printer) DoExpressionStat(s *AST.ExpressionStat) {
|
||||||
switch s.Tok {
|
switch s.Tok {
|
||||||
case Scanner.ILLEGAL:
|
case token.ILLEGAL:
|
||||||
P.Expr(s.Expr);
|
P.Expr(s.Expr);
|
||||||
case Scanner.INC, Scanner.DEC:
|
case token.INC, token.DEC:
|
||||||
P.Expr(s.Expr);
|
P.Expr(s.Expr);
|
||||||
P.Token(s.Pos, s.Tok);
|
P.Token(s.Pos, s.Tok);
|
||||||
case Scanner.RETURN, Scanner.GO, Scanner.DEFER:
|
case token.RETURN, token.GO, token.DEFER:
|
||||||
P.Token(s.Pos, s.Tok);
|
P.Token(s.Pos, s.Tok);
|
||||||
if s.Expr != nil {
|
if s.Expr != nil {
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
@ -861,14 +861,14 @@ func (P *Printer) ControlClause(isForStat bool, init AST.Stat, expr AST.Expr, po
|
|||||||
P.Stat(init);
|
P.Stat(init);
|
||||||
P.separator = none;
|
P.separator = none;
|
||||||
}
|
}
|
||||||
P.Token(0, Scanner.SEMICOLON);
|
P.Token(0, token.SEMICOLON);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
if expr != nil {
|
if expr != nil {
|
||||||
P.Expr(expr);
|
P.Expr(expr);
|
||||||
P.separator = none;
|
P.separator = none;
|
||||||
}
|
}
|
||||||
if isForStat {
|
if isForStat {
|
||||||
P.Token(0, Scanner.SEMICOLON);
|
P.Token(0, token.SEMICOLON);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
if post != nil {
|
if post != nil {
|
||||||
P.Stat(post);
|
P.Stat(post);
|
||||||
@ -880,12 +880,12 @@ func (P *Printer) ControlClause(isForStat bool, init AST.Stat, expr AST.Expr, po
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoIfStat(s *AST.IfStat) {
|
func (P *Printer) DoIfStat(s *AST.IfStat) {
|
||||||
P.Token(s.Pos, Scanner.IF);
|
P.Token(s.Pos, token.IF);
|
||||||
P.ControlClause(false, s.Init, s.Cond, nil);
|
P.ControlClause(false, s.Init, s.Cond, nil);
|
||||||
P.Block(s.Body, true);
|
P.Block(s.Body, true);
|
||||||
if s.Else != nil {
|
if s.Else != nil {
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Token(0, Scanner.ELSE);
|
P.Token(0, token.ELSE);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Stat(s.Else);
|
P.Stat(s.Else);
|
||||||
}
|
}
|
||||||
@ -893,7 +893,7 @@ func (P *Printer) DoIfStat(s *AST.IfStat) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoForStat(s *AST.ForStat) {
|
func (P *Printer) DoForStat(s *AST.ForStat) {
|
||||||
P.Token(s.Pos, Scanner.FOR);
|
P.Token(s.Pos, token.FOR);
|
||||||
P.ControlClause(true, s.Init, s.Cond, s.Post);
|
P.ControlClause(true, s.Init, s.Cond, s.Post);
|
||||||
P.Block(s.Body, true);
|
P.Block(s.Body, true);
|
||||||
}
|
}
|
||||||
@ -901,15 +901,15 @@ func (P *Printer) DoForStat(s *AST.ForStat) {
|
|||||||
|
|
||||||
func (P *Printer) DoCaseClause(s *AST.CaseClause) {
|
func (P *Printer) DoCaseClause(s *AST.CaseClause) {
|
||||||
if s.Expr != nil {
|
if s.Expr != nil {
|
||||||
P.Token(s.Pos, Scanner.CASE);
|
P.Token(s.Pos, token.CASE);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Expr(s.Expr);
|
P.Expr(s.Expr);
|
||||||
} else {
|
} else {
|
||||||
P.Token(s.Pos, Scanner.DEFAULT);
|
P.Token(s.Pos, token.DEFAULT);
|
||||||
}
|
}
|
||||||
// TODO: try to use P.Block instead
|
// TODO: try to use P.Block instead
|
||||||
// P.Block(s.Body, true);
|
// P.Block(s.Body, true);
|
||||||
P.Token(s.Body.Pos, Scanner.COLON);
|
P.Token(s.Body.Pos, token.COLON);
|
||||||
P.indentation++;
|
P.indentation++;
|
||||||
P.StatementList(s.Body.List);
|
P.StatementList(s.Body.List);
|
||||||
P.indentation--;
|
P.indentation--;
|
||||||
@ -918,14 +918,14 @@ func (P *Printer) DoCaseClause(s *AST.CaseClause) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoSwitchStat(s *AST.SwitchStat) {
|
func (P *Printer) DoSwitchStat(s *AST.SwitchStat) {
|
||||||
P.Token(s.Pos, Scanner.SWITCH);
|
P.Token(s.Pos, token.SWITCH);
|
||||||
P.ControlClause(false, s.Init, s.Tag, nil);
|
P.ControlClause(false, s.Init, s.Tag, nil);
|
||||||
P.Block(s.Body, false);
|
P.Block(s.Body, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoSelectStat(s *AST.SelectStat) {
|
func (P *Printer) DoSelectStat(s *AST.SelectStat) {
|
||||||
P.Token(s.Pos, Scanner.SELECT);
|
P.Token(s.Pos, token.SELECT);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Block(s.Body, false);
|
P.Block(s.Body, false);
|
||||||
}
|
}
|
||||||
@ -955,7 +955,7 @@ func (P *Printer) DoBadDecl(d *AST.BadDecl) {
|
|||||||
|
|
||||||
func (P *Printer) DoImportDecl(d *AST.ImportDecl) {
|
func (P *Printer) DoImportDecl(d *AST.ImportDecl) {
|
||||||
if d.Pos > 0 {
|
if d.Pos > 0 {
|
||||||
P.Token(d.Pos, Scanner.IMPORT);
|
P.Token(d.Pos, token.IMPORT);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
}
|
}
|
||||||
if d.Ident != nil {
|
if d.Ident != nil {
|
||||||
@ -964,7 +964,7 @@ func (P *Printer) DoImportDecl(d *AST.ImportDecl) {
|
|||||||
P.String(d.Path.Pos(), ""); // flush pending ';' separator/newlines
|
P.String(d.Path.Pos(), ""); // flush pending ';' separator/newlines
|
||||||
}
|
}
|
||||||
P.separator = tab;
|
P.separator = tab;
|
||||||
if lit, is_lit := d.Path.(*AST.BasicLit); is_lit && lit.Tok == Scanner.STRING {
|
if lit, is_lit := d.Path.(*AST.BasicLit); is_lit && lit.Tok == token.STRING {
|
||||||
P.HtmlPackageName(lit.Pos_, lit.Val);
|
P.HtmlPackageName(lit.Pos_, lit.Val);
|
||||||
} else {
|
} else {
|
||||||
// we should only reach here for strange imports
|
// we should only reach here for strange imports
|
||||||
@ -977,7 +977,7 @@ func (P *Printer) DoImportDecl(d *AST.ImportDecl) {
|
|||||||
|
|
||||||
func (P *Printer) DoConstDecl(d *AST.ConstDecl) {
|
func (P *Printer) DoConstDecl(d *AST.ConstDecl) {
|
||||||
if d.Pos > 0 {
|
if d.Pos > 0 {
|
||||||
P.Token(d.Pos, Scanner.CONST);
|
P.Token(d.Pos, token.CONST);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
}
|
}
|
||||||
P.Idents(d.Idents);
|
P.Idents(d.Idents);
|
||||||
@ -987,7 +987,7 @@ func (P *Printer) DoConstDecl(d *AST.ConstDecl) {
|
|||||||
}
|
}
|
||||||
if d.Vals != nil {
|
if d.Vals != nil {
|
||||||
P.separator = tab;
|
P.separator = tab;
|
||||||
P.Token(0, Scanner.ASSIGN);
|
P.Token(0, token.ASSIGN);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Expr(d.Vals);
|
P.Expr(d.Vals);
|
||||||
}
|
}
|
||||||
@ -997,7 +997,7 @@ func (P *Printer) DoConstDecl(d *AST.ConstDecl) {
|
|||||||
|
|
||||||
func (P *Printer) DoTypeDecl(d *AST.TypeDecl) {
|
func (P *Printer) DoTypeDecl(d *AST.TypeDecl) {
|
||||||
if d.Pos > 0 {
|
if d.Pos > 0 {
|
||||||
P.Token(d.Pos, Scanner.TYPE);
|
P.Token(d.Pos, token.TYPE);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
}
|
}
|
||||||
P.Expr(d.Ident);
|
P.Expr(d.Ident);
|
||||||
@ -1009,7 +1009,7 @@ func (P *Printer) DoTypeDecl(d *AST.TypeDecl) {
|
|||||||
|
|
||||||
func (P *Printer) DoVarDecl(d *AST.VarDecl) {
|
func (P *Printer) DoVarDecl(d *AST.VarDecl) {
|
||||||
if d.Pos > 0 {
|
if d.Pos > 0 {
|
||||||
P.Token(d.Pos, Scanner.VAR);
|
P.Token(d.Pos, token.VAR);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
}
|
}
|
||||||
P.Idents(d.Idents);
|
P.Idents(d.Idents);
|
||||||
@ -1020,7 +1020,7 @@ func (P *Printer) DoVarDecl(d *AST.VarDecl) {
|
|||||||
}
|
}
|
||||||
if d.Vals != nil {
|
if d.Vals != nil {
|
||||||
P.separator = tab;
|
P.separator = tab;
|
||||||
P.Token(0, Scanner.ASSIGN);
|
P.Token(0, token.ASSIGN);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Expr(d.Vals);
|
P.Expr(d.Vals);
|
||||||
}
|
}
|
||||||
@ -1029,17 +1029,17 @@ func (P *Printer) DoVarDecl(d *AST.VarDecl) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoFuncDecl(d *AST.FuncDecl) {
|
func (P *Printer) DoFuncDecl(d *AST.FuncDecl) {
|
||||||
P.Token(d.Pos_, Scanner.FUNC);
|
P.Token(d.Pos_, token.FUNC);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
if recv := d.Recv; recv != nil {
|
if recv := d.Recv; recv != nil {
|
||||||
// method: print receiver
|
// method: print receiver
|
||||||
P.Token(0, Scanner.LPAREN);
|
P.Token(0, token.LPAREN);
|
||||||
if len(recv.Idents) > 0 {
|
if len(recv.Idents) > 0 {
|
||||||
P.Expr(recv.Idents[0]);
|
P.Expr(recv.Idents[0]);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
}
|
}
|
||||||
P.Expr(recv.Typ);
|
P.Expr(recv.Typ);
|
||||||
P.Token(0, Scanner.RPAREN);
|
P.Token(0, token.RPAREN);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
}
|
}
|
||||||
P.Expr(d.Ident);
|
P.Expr(d.Ident);
|
||||||
@ -1053,7 +1053,7 @@ func (P *Printer) DoFuncDecl(d *AST.FuncDecl) {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Printer) DoDeclList(d *AST.DeclList) {
|
func (P *Printer) DoDeclList(d *AST.DeclList) {
|
||||||
if !*def || d.Tok == Scanner.IMPORT || d.Tok == Scanner.VAR {
|
if !*def || d.Tok == token.IMPORT || d.Tok == token.VAR {
|
||||||
P.Token(d.Pos, d.Tok);
|
P.Token(d.Pos, d.Tok);
|
||||||
} else {
|
} else {
|
||||||
P.String(d.Pos, "def");
|
P.String(d.Pos, "def");
|
||||||
@ -1062,7 +1062,7 @@ func (P *Printer) DoDeclList(d *AST.DeclList) {
|
|||||||
|
|
||||||
// group of parenthesized declarations
|
// group of parenthesized declarations
|
||||||
P.state = opening_scope;
|
P.state = opening_scope;
|
||||||
P.Token(0, Scanner.LPAREN);
|
P.Token(0, token.LPAREN);
|
||||||
if len(d.List) > 0 {
|
if len(d.List) > 0 {
|
||||||
P.newlines = 1;
|
P.newlines = 1;
|
||||||
for i := 0; i < len(d.List); i++ {
|
for i := 0; i < len(d.List); i++ {
|
||||||
@ -1074,7 +1074,7 @@ func (P *Printer) DoDeclList(d *AST.DeclList) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
P.state = closing_scope;
|
P.state = closing_scope;
|
||||||
P.Token(d.End, Scanner.RPAREN);
|
P.Token(d.End, token.RPAREN);
|
||||||
P.opt_semi = true;
|
P.opt_semi = true;
|
||||||
P.newlines = 2;
|
P.newlines = 2;
|
||||||
}
|
}
|
||||||
@ -1089,7 +1089,7 @@ func (P *Printer) Decl(d AST.Decl) {
|
|||||||
// Program
|
// Program
|
||||||
|
|
||||||
func (P *Printer) Program(p *AST.Program) {
|
func (P *Printer) Program(p *AST.Program) {
|
||||||
P.Token(p.Pos, Scanner.PACKAGE);
|
P.Token(p.Pos, token.PACKAGE);
|
||||||
P.separator = blank;
|
P.separator = blank;
|
||||||
P.Expr(p.Ident);
|
P.Expr(p.Ident);
|
||||||
P.newlines = 1;
|
P.newlines = 1;
|
||||||
|
@ -4,272 +4,33 @@
|
|||||||
|
|
||||||
package scanner
|
package scanner
|
||||||
|
|
||||||
|
// A Go scanner. Takes a []byte as source which can then be
|
||||||
|
// tokenized through repeated calls to the Scan() function.
|
||||||
|
//
|
||||||
|
// Sample use:
|
||||||
|
//
|
||||||
|
// import "token"
|
||||||
|
// import "scanner"
|
||||||
|
//
|
||||||
|
// func tokenize(src []byte) {
|
||||||
|
// var s scanner.Scanner;
|
||||||
|
// s.Init(src, nil, false);
|
||||||
|
// for {
|
||||||
|
// pos, tok, lit := s.Scan();
|
||||||
|
// if tok == Scanner.EOF {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// println(pos, token.TokenString(tok), string(lit));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"utf8";
|
"utf8";
|
||||||
"unicode";
|
"unicode";
|
||||||
"strconv";
|
"strconv";
|
||||||
|
"token";
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
ILLEGAL = iota;
|
|
||||||
EOF;
|
|
||||||
|
|
||||||
INT;
|
|
||||||
FLOAT;
|
|
||||||
STRING;
|
|
||||||
IDENT;
|
|
||||||
COMMENT;
|
|
||||||
|
|
||||||
ADD;
|
|
||||||
SUB;
|
|
||||||
MUL;
|
|
||||||
QUO;
|
|
||||||
REM;
|
|
||||||
|
|
||||||
AND;
|
|
||||||
OR;
|
|
||||||
XOR;
|
|
||||||
SHL;
|
|
||||||
SHR;
|
|
||||||
|
|
||||||
ADD_ASSIGN;
|
|
||||||
SUB_ASSIGN;
|
|
||||||
MUL_ASSIGN;
|
|
||||||
QUO_ASSIGN;
|
|
||||||
REM_ASSIGN;
|
|
||||||
|
|
||||||
AND_ASSIGN;
|
|
||||||
OR_ASSIGN;
|
|
||||||
XOR_ASSIGN;
|
|
||||||
SHL_ASSIGN;
|
|
||||||
SHR_ASSIGN;
|
|
||||||
|
|
||||||
LAND;
|
|
||||||
LOR;
|
|
||||||
ARROW;
|
|
||||||
INC;
|
|
||||||
DEC;
|
|
||||||
|
|
||||||
EQL;
|
|
||||||
LSS;
|
|
||||||
GTR;
|
|
||||||
ASSIGN;
|
|
||||||
NOT;
|
|
||||||
|
|
||||||
NEQ;
|
|
||||||
LEQ;
|
|
||||||
GEQ;
|
|
||||||
DEFINE;
|
|
||||||
ELLIPSIS;
|
|
||||||
|
|
||||||
LPAREN;
|
|
||||||
LBRACK;
|
|
||||||
LBRACE;
|
|
||||||
COMMA;
|
|
||||||
PERIOD;
|
|
||||||
|
|
||||||
RPAREN;
|
|
||||||
RBRACK;
|
|
||||||
RBRACE;
|
|
||||||
SEMICOLON;
|
|
||||||
COLON;
|
|
||||||
|
|
||||||
// keywords
|
|
||||||
keywords_beg;
|
|
||||||
BREAK;
|
|
||||||
CASE;
|
|
||||||
CHAN;
|
|
||||||
CONST;
|
|
||||||
CONTINUE;
|
|
||||||
|
|
||||||
DEFAULT;
|
|
||||||
DEFER;
|
|
||||||
ELSE;
|
|
||||||
FALLTHROUGH;
|
|
||||||
FOR;
|
|
||||||
|
|
||||||
FUNC;
|
|
||||||
GO;
|
|
||||||
GOTO;
|
|
||||||
IF;
|
|
||||||
IMPORT;
|
|
||||||
|
|
||||||
INTERFACE;
|
|
||||||
MAP;
|
|
||||||
PACKAGE;
|
|
||||||
RANGE;
|
|
||||||
RETURN;
|
|
||||||
|
|
||||||
SELECT;
|
|
||||||
STRUCT;
|
|
||||||
SWITCH;
|
|
||||||
TYPE;
|
|
||||||
VAR;
|
|
||||||
keywords_end;
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func TokenString(tok int) string {
|
|
||||||
switch tok {
|
|
||||||
case ILLEGAL: return "ILLEGAL";
|
|
||||||
case EOF: return "EOF";
|
|
||||||
|
|
||||||
case INT: return "INT";
|
|
||||||
case FLOAT: return "FLOAT";
|
|
||||||
case STRING: return "STRING";
|
|
||||||
case IDENT: return "IDENT";
|
|
||||||
case COMMENT: return "COMMENT";
|
|
||||||
|
|
||||||
case ADD: return "+";
|
|
||||||
case SUB: return "-";
|
|
||||||
case MUL: return "*";
|
|
||||||
case QUO: return "/";
|
|
||||||
case REM: return "%";
|
|
||||||
|
|
||||||
case AND: return "&";
|
|
||||||
case OR: return "|";
|
|
||||||
case XOR: return "^";
|
|
||||||
case SHL: return "<<";
|
|
||||||
case SHR: return ">>";
|
|
||||||
|
|
||||||
case ADD_ASSIGN: return "+=";
|
|
||||||
case SUB_ASSIGN: return "-=";
|
|
||||||
case MUL_ASSIGN: return "+=";
|
|
||||||
case QUO_ASSIGN: return "/=";
|
|
||||||
case REM_ASSIGN: return "%=";
|
|
||||||
|
|
||||||
case AND_ASSIGN: return "&=";
|
|
||||||
case OR_ASSIGN: return "|=";
|
|
||||||
case XOR_ASSIGN: return "^=";
|
|
||||||
case SHL_ASSIGN: return "<<=";
|
|
||||||
case SHR_ASSIGN: return ">>=";
|
|
||||||
|
|
||||||
case LAND: return "&&";
|
|
||||||
case LOR: return "||";
|
|
||||||
case ARROW: return "<-";
|
|
||||||
case INC: return "++";
|
|
||||||
case DEC: return "--";
|
|
||||||
|
|
||||||
case EQL: return "==";
|
|
||||||
case LSS: return "<";
|
|
||||||
case GTR: return ">";
|
|
||||||
case ASSIGN: return "=";
|
|
||||||
case NOT: return "!";
|
|
||||||
|
|
||||||
case NEQ: return "!=";
|
|
||||||
case LEQ: return "<=";
|
|
||||||
case GEQ: return ">=";
|
|
||||||
case DEFINE: return ":=";
|
|
||||||
case ELLIPSIS: return "...";
|
|
||||||
|
|
||||||
case LPAREN: return "(";
|
|
||||||
case LBRACK: return "[";
|
|
||||||
case LBRACE: return "{";
|
|
||||||
case COMMA: return ",";
|
|
||||||
case PERIOD: return ".";
|
|
||||||
|
|
||||||
case RPAREN: return ")";
|
|
||||||
case RBRACK: return "]";
|
|
||||||
case RBRACE: return "}";
|
|
||||||
case SEMICOLON: return ";";
|
|
||||||
case COLON: return ":";
|
|
||||||
|
|
||||||
case BREAK: return "break";
|
|
||||||
case CASE: return "case";
|
|
||||||
case CHAN: return "chan";
|
|
||||||
case CONST: return "const";
|
|
||||||
case CONTINUE: return "continue";
|
|
||||||
|
|
||||||
case DEFAULT: return "default";
|
|
||||||
case DEFER: return "defer";
|
|
||||||
case ELSE: return "else";
|
|
||||||
case FALLTHROUGH: return "fallthrough";
|
|
||||||
case FOR: return "for";
|
|
||||||
|
|
||||||
case FUNC: return "func";
|
|
||||||
case GO: return "go";
|
|
||||||
case GOTO: return "goto";
|
|
||||||
case IF: return "if";
|
|
||||||
case IMPORT: return "import";
|
|
||||||
|
|
||||||
case INTERFACE: return "interface";
|
|
||||||
case MAP: return "map";
|
|
||||||
case PACKAGE: return "package";
|
|
||||||
case RANGE: return "range";
|
|
||||||
case RETURN: return "return";
|
|
||||||
|
|
||||||
case SELECT: return "select";
|
|
||||||
case STRUCT: return "struct";
|
|
||||||
case SWITCH: return "switch";
|
|
||||||
case TYPE: return "type";
|
|
||||||
case VAR: return "var";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "token(" + strconv.Itoa(tok) + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const (
|
|
||||||
LowestPrec = -1;
|
|
||||||
UnaryPrec = 7;
|
|
||||||
HighestPrec = 8;
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func Precedence(tok int) int {
|
|
||||||
switch tok {
|
|
||||||
case COLON:
|
|
||||||
return 0;
|
|
||||||
case LOR:
|
|
||||||
return 1;
|
|
||||||
case LAND:
|
|
||||||
return 2;
|
|
||||||
case ARROW:
|
|
||||||
return 3;
|
|
||||||
case EQL, NEQ, LSS, LEQ, GTR, GEQ:
|
|
||||||
return 4;
|
|
||||||
case ADD, SUB, OR, XOR:
|
|
||||||
return 5;
|
|
||||||
case MUL, QUO, REM, SHL, SHR, AND:
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
return LowestPrec;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var keywords map [string] int;
|
|
||||||
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
keywords = make(map [string] int);
|
|
||||||
for i := keywords_beg + 1; i < keywords_end; i++ {
|
|
||||||
keywords[TokenString(i)] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func is_letter(ch int) bool {
|
|
||||||
return
|
|
||||||
'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || // common case
|
|
||||||
ch == '_' || unicode.IsLetter(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func digit_val(ch int) int {
|
|
||||||
// TODO: spec permits other Unicode digits as well
|
|
||||||
if '0' <= ch && ch <= '9' {
|
|
||||||
return ch - '0';
|
|
||||||
}
|
|
||||||
if 'a' <= ch && ch <= 'f' {
|
|
||||||
return ch - 'a' + 10;
|
|
||||||
}
|
|
||||||
if 'A' <= ch && ch <= 'F' {
|
|
||||||
return ch - 'A' + 10;
|
|
||||||
}
|
|
||||||
return 16; // larger than any legal digit val
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
type ErrorHandler interface {
|
type ErrorHandler interface {
|
||||||
Error(pos int, msg string);
|
Error(pos int, msg string);
|
||||||
}
|
}
|
||||||
@ -288,6 +49,28 @@ type Scanner struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func is_letter(ch int) bool {
|
||||||
|
return
|
||||||
|
'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || // common case
|
||||||
|
ch == '_' || unicode.IsLetter(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func digit_val(ch int) int {
|
||||||
|
// TODO spec permits other Unicode digits as well
|
||||||
|
if '0' <= ch && ch <= '9' {
|
||||||
|
return ch - '0';
|
||||||
|
}
|
||||||
|
if 'a' <= ch && ch <= 'f' {
|
||||||
|
return ch - 'a' + 10;
|
||||||
|
}
|
||||||
|
if 'A' <= ch && ch <= 'F' {
|
||||||
|
return ch - 'A' + 10;
|
||||||
|
}
|
||||||
|
return 16; // larger than any legal digit val
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Read the next Unicode char into S.ch.
|
// Read the next Unicode char into S.ch.
|
||||||
// S.ch < 0 means end-of-file.
|
// S.ch < 0 means end-of-file.
|
||||||
func (S *Scanner) next() {
|
func (S *Scanner) next() {
|
||||||
@ -308,10 +91,12 @@ func (S *Scanner) next() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (S *Scanner) error(pos int, msg string) {
|
// Initialize the scanner.
|
||||||
S.err.Error(pos, msg);
|
//
|
||||||
}
|
// The error handler (err) is called when an illegal token is encountered.
|
||||||
|
// If scan_comments is set to true, newline characters ('\n') and comments
|
||||||
|
// are recognized as token.COMMENT, otherwise they are treated as white
|
||||||
|
// space and ignored.
|
||||||
|
|
||||||
func (S *Scanner) Init(src []byte, err ErrorHandler, scan_comments bool) {
|
func (S *Scanner) Init(src []byte, err ErrorHandler, scan_comments bool) {
|
||||||
S.src = src;
|
S.src = src;
|
||||||
@ -338,6 +123,11 @@ func charString(ch int) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (S *Scanner) error(pos int, msg string) {
|
||||||
|
S.err.Error(pos, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (S *Scanner) expect(ch int) {
|
func (S *Scanner) expect(ch int) {
|
||||||
if S.ch != ch {
|
if S.ch != ch {
|
||||||
S.error(S.chpos, "expected " + charString(ch) + ", found " + charString(S.ch));
|
S.error(S.chpos, "expected " + charString(ch) + ", found " + charString(S.ch));
|
||||||
@ -400,20 +190,13 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (S *Scanner) scanIdentifier() (tok int, val []byte) {
|
func (S *Scanner) scanIdentifier() (tok int, lit []byte) {
|
||||||
pos := S.chpos;
|
pos := S.chpos;
|
||||||
for is_letter(S.ch) || digit_val(S.ch) < 10 {
|
for is_letter(S.ch) || digit_val(S.ch) < 10 {
|
||||||
S.next();
|
S.next();
|
||||||
}
|
}
|
||||||
val = S.src[pos : S.chpos];
|
lit = S.src[pos : S.chpos];
|
||||||
|
return token.Lookup(lit), lit;
|
||||||
var present bool;
|
|
||||||
tok, present = keywords[string(val)];
|
|
||||||
if !present {
|
|
||||||
tok = IDENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tok, val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -424,12 +207,12 @@ func (S *Scanner) scanMantissa(base int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (S *Scanner) scanNumber(seen_decimal_point bool) (tok int, val []byte) {
|
func (S *Scanner) scanNumber(seen_decimal_point bool) (tok int, lit []byte) {
|
||||||
pos := S.chpos;
|
pos := S.chpos;
|
||||||
tok = INT;
|
tok = token.INT;
|
||||||
|
|
||||||
if seen_decimal_point {
|
if seen_decimal_point {
|
||||||
tok = FLOAT;
|
tok = token.FLOAT;
|
||||||
pos--; // '.' is one byte
|
pos--; // '.' is one byte
|
||||||
S.scanMantissa(10);
|
S.scanMantissa(10);
|
||||||
goto exponent;
|
goto exponent;
|
||||||
@ -447,7 +230,7 @@ func (S *Scanner) scanNumber(seen_decimal_point bool) (tok int, val []byte) {
|
|||||||
S.scanMantissa(8);
|
S.scanMantissa(8);
|
||||||
if digit_val(S.ch) < 10 || S.ch == '.' || S.ch == 'e' || S.ch == 'E' {
|
if digit_val(S.ch) < 10 || S.ch == '.' || S.ch == 'e' || S.ch == 'E' {
|
||||||
// float
|
// float
|
||||||
tok = FLOAT;
|
tok = token.FLOAT;
|
||||||
goto mantissa;
|
goto mantissa;
|
||||||
}
|
}
|
||||||
// octal int
|
// octal int
|
||||||
@ -461,7 +244,7 @@ mantissa:
|
|||||||
|
|
||||||
if S.ch == '.' {
|
if S.ch == '.' {
|
||||||
// float
|
// float
|
||||||
tok = FLOAT;
|
tok = token.FLOAT;
|
||||||
S.next();
|
S.next();
|
||||||
S.scanMantissa(10)
|
S.scanMantissa(10)
|
||||||
}
|
}
|
||||||
@ -469,7 +252,7 @@ mantissa:
|
|||||||
exponent:
|
exponent:
|
||||||
if S.ch == 'e' || S.ch == 'E' {
|
if S.ch == 'e' || S.ch == 'E' {
|
||||||
// float
|
// float
|
||||||
tok = FLOAT;
|
tok = token.FLOAT;
|
||||||
S.next();
|
S.next();
|
||||||
if S.ch == '-' || S.ch == '+' {
|
if S.ch == '-' || S.ch == '+' {
|
||||||
S.next();
|
S.next();
|
||||||
@ -607,75 +390,78 @@ func (S *Scanner) select4(tok0, tok1, ch2, tok2, tok3 int) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (S *Scanner) Scan() (pos, tok int, val []byte) {
|
// Scans the next token. Returns the token byte position in the source,
|
||||||
|
// its token value, and the corresponding literal text if the token is
|
||||||
|
// an identifier or basic type literals (token.IsLiteral(tok) == true).
|
||||||
|
|
||||||
|
func (S *Scanner) Scan() (pos, tok int, lit []byte) {
|
||||||
loop:
|
loop:
|
||||||
S.skipWhitespace();
|
S.skipWhitespace();
|
||||||
|
|
||||||
pos, tok = S.chpos, ILLEGAL;
|
pos, tok = S.chpos, token.ILLEGAL;
|
||||||
|
|
||||||
switch ch := S.ch; {
|
switch ch := S.ch; {
|
||||||
case is_letter(ch): tok, val = S.scanIdentifier();
|
case is_letter(ch): tok, lit = S.scanIdentifier();
|
||||||
case digit_val(ch) < 10: tok, val = S.scanNumber(false);
|
case digit_val(ch) < 10: tok, lit = S.scanNumber(false);
|
||||||
default:
|
default:
|
||||||
S.next(); // always make progress
|
S.next(); // always make progress
|
||||||
switch ch {
|
switch ch {
|
||||||
case -1: tok = EOF;
|
case -1: tok = token.EOF;
|
||||||
case '\n': tok, val = COMMENT, []byte{'\n'};
|
case '\n': tok, lit = token.COMMENT, []byte{'\n'};
|
||||||
case '"': tok, val = STRING, S.scanString();
|
case '"': tok, lit = token.STRING, S.scanString();
|
||||||
case '\'': tok, val = INT, S.scanChar();
|
case '\'': tok, lit = token.CHAR, S.scanChar();
|
||||||
case '`': tok, val = STRING, S.scanRawString();
|
case '`': tok, lit = token.STRING, S.scanRawString();
|
||||||
case ':': tok = S.select2(COLON, DEFINE);
|
case ':': tok = S.select2(token.COLON, token.DEFINE);
|
||||||
case '.':
|
case '.':
|
||||||
if digit_val(S.ch) < 10 {
|
if digit_val(S.ch) < 10 {
|
||||||
tok, val = S.scanNumber(true);
|
tok, lit = S.scanNumber(true);
|
||||||
} else if S.ch == '.' {
|
} else if S.ch == '.' {
|
||||||
S.next();
|
S.next();
|
||||||
if S.ch == '.' {
|
if S.ch == '.' {
|
||||||
S.next();
|
S.next();
|
||||||
tok = ELLIPSIS;
|
tok = token.ELLIPSIS;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tok = PERIOD;
|
tok = token.PERIOD;
|
||||||
}
|
}
|
||||||
case ',': tok = COMMA;
|
case ',': tok = token.COMMA;
|
||||||
case ';': tok = SEMICOLON;
|
case ';': tok = token.SEMICOLON;
|
||||||
case '(': tok = LPAREN;
|
case '(': tok = token.LPAREN;
|
||||||
case ')': tok = RPAREN;
|
case ')': tok = token.RPAREN;
|
||||||
case '[': tok = LBRACK;
|
case '[': tok = token.LBRACK;
|
||||||
case ']': tok = RBRACK;
|
case ']': tok = token.RBRACK;
|
||||||
case '{': tok = LBRACE;
|
case '{': tok = token.LBRACE;
|
||||||
case '}': tok = RBRACE;
|
case '}': tok = token.RBRACE;
|
||||||
case '+': tok = S.select3(ADD, ADD_ASSIGN, '+', INC);
|
case '+': tok = S.select3(token.ADD, token.ADD_ASSIGN, '+', token.INC);
|
||||||
case '-': tok = S.select3(SUB, SUB_ASSIGN, '-', DEC);
|
case '-': tok = S.select3(token.SUB, token.SUB_ASSIGN, '-', token.DEC);
|
||||||
case '*': tok = S.select2(MUL, MUL_ASSIGN);
|
case '*': tok = S.select2(token.MUL, token.MUL_ASSIGN);
|
||||||
case '/':
|
case '/':
|
||||||
if S.ch == '/' || S.ch == '*' {
|
if S.ch == '/' || S.ch == '*' {
|
||||||
tok, val = COMMENT, S.scanComment();
|
tok, lit = token.COMMENT, S.scanComment();
|
||||||
if !S.scan_comments {
|
if !S.scan_comments {
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tok = S.select2(QUO, QUO_ASSIGN);
|
tok = S.select2(token.QUO, token.QUO_ASSIGN);
|
||||||
}
|
}
|
||||||
case '%': tok = S.select2(REM, REM_ASSIGN);
|
case '%': tok = S.select2(token.REM, token.REM_ASSIGN);
|
||||||
case '^': tok = S.select2(XOR, XOR_ASSIGN);
|
case '^': tok = S.select2(token.XOR, token.XOR_ASSIGN);
|
||||||
case '<':
|
case '<':
|
||||||
if S.ch == '-' {
|
if S.ch == '-' {
|
||||||
S.next();
|
S.next();
|
||||||
tok = ARROW;
|
tok = token.ARROW;
|
||||||
} else {
|
} else {
|
||||||
tok = S.select4(LSS, LEQ, '<', SHL, SHL_ASSIGN);
|
tok = S.select4(token.LSS, token.LEQ, '<', token.SHL, token.SHL_ASSIGN);
|
||||||
}
|
}
|
||||||
case '>': tok = S.select4(GTR, GEQ, '>', SHR, SHR_ASSIGN);
|
case '>': tok = S.select4(token.GTR, token.GEQ, '>', token.SHR, token.SHR_ASSIGN);
|
||||||
case '=': tok = S.select2(ASSIGN, EQL);
|
case '=': tok = S.select2(token.ASSIGN, token.EQL);
|
||||||
case '!': tok = S.select2(NOT, NEQ);
|
case '!': tok = S.select2(token.NOT, token.NEQ);
|
||||||
case '&': tok = S.select3(AND, AND_ASSIGN, '&', LAND);
|
case '&': tok = S.select3(token.AND, token.AND_ASSIGN, '&', token.LAND);
|
||||||
case '|': tok = S.select3(OR, OR_ASSIGN, '|', LOR);
|
case '|': tok = S.select3(token.OR, token.OR_ASSIGN, '|', token.LOR);
|
||||||
default:
|
default:
|
||||||
S.error(pos, "illegal character " + charString(ch));
|
S.error(pos, "illegal character " + charString(ch));
|
||||||
tok = ILLEGAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pos, tok, val;
|
return pos, tok, lit;
|
||||||
}
|
}
|
||||||
|
286
usr/gri/pretty/token.go
Normal file
286
usr/gri/pretty/token.go
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
// 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 token
|
||||||
|
|
||||||
|
// Defines Go tokens and basic token operations.
|
||||||
|
|
||||||
|
import "strconv";
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Special tokens
|
||||||
|
ILLEGAL = iota;
|
||||||
|
EOF;
|
||||||
|
COMMENT;
|
||||||
|
|
||||||
|
// Identifiers and basic type literals
|
||||||
|
// (these tokens stand for classes of literals)
|
||||||
|
literal_beg;
|
||||||
|
IDENT;
|
||||||
|
INT;
|
||||||
|
FLOAT;
|
||||||
|
CHAR;
|
||||||
|
STRING;
|
||||||
|
literal_end;
|
||||||
|
|
||||||
|
// Operators and delimiters
|
||||||
|
operator_beg;
|
||||||
|
ADD;
|
||||||
|
SUB;
|
||||||
|
MUL;
|
||||||
|
QUO;
|
||||||
|
REM;
|
||||||
|
|
||||||
|
AND;
|
||||||
|
OR;
|
||||||
|
XOR;
|
||||||
|
SHL;
|
||||||
|
SHR;
|
||||||
|
|
||||||
|
ADD_ASSIGN;
|
||||||
|
SUB_ASSIGN;
|
||||||
|
MUL_ASSIGN;
|
||||||
|
QUO_ASSIGN;
|
||||||
|
REM_ASSIGN;
|
||||||
|
|
||||||
|
AND_ASSIGN;
|
||||||
|
OR_ASSIGN;
|
||||||
|
XOR_ASSIGN;
|
||||||
|
SHL_ASSIGN;
|
||||||
|
SHR_ASSIGN;
|
||||||
|
|
||||||
|
LAND;
|
||||||
|
LOR;
|
||||||
|
ARROW;
|
||||||
|
INC;
|
||||||
|
DEC;
|
||||||
|
|
||||||
|
EQL;
|
||||||
|
LSS;
|
||||||
|
GTR;
|
||||||
|
ASSIGN;
|
||||||
|
NOT;
|
||||||
|
|
||||||
|
NEQ;
|
||||||
|
LEQ;
|
||||||
|
GEQ;
|
||||||
|
DEFINE;
|
||||||
|
ELLIPSIS;
|
||||||
|
|
||||||
|
LPAREN;
|
||||||
|
LBRACK;
|
||||||
|
LBRACE;
|
||||||
|
COMMA;
|
||||||
|
PERIOD;
|
||||||
|
|
||||||
|
RPAREN;
|
||||||
|
RBRACK;
|
||||||
|
RBRACE;
|
||||||
|
SEMICOLON;
|
||||||
|
COLON;
|
||||||
|
operator_end;
|
||||||
|
|
||||||
|
// Keywords
|
||||||
|
keyword_beg;
|
||||||
|
BREAK;
|
||||||
|
CASE;
|
||||||
|
CHAN;
|
||||||
|
CONST;
|
||||||
|
CONTINUE;
|
||||||
|
|
||||||
|
DEFAULT;
|
||||||
|
DEFER;
|
||||||
|
ELSE;
|
||||||
|
FALLTHROUGH;
|
||||||
|
FOR;
|
||||||
|
|
||||||
|
FUNC;
|
||||||
|
GO;
|
||||||
|
GOTO;
|
||||||
|
IF;
|
||||||
|
IMPORT;
|
||||||
|
|
||||||
|
INTERFACE;
|
||||||
|
MAP;
|
||||||
|
PACKAGE;
|
||||||
|
RANGE;
|
||||||
|
RETURN;
|
||||||
|
|
||||||
|
SELECT;
|
||||||
|
STRUCT;
|
||||||
|
SWITCH;
|
||||||
|
TYPE;
|
||||||
|
VAR;
|
||||||
|
keyword_end;
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func TokenString(tok int) string {
|
||||||
|
switch tok {
|
||||||
|
case ILLEGAL: return "ILLEGAL";
|
||||||
|
|
||||||
|
case EOF: return "EOF";
|
||||||
|
case COMMENT: return "COMMENT";
|
||||||
|
|
||||||
|
case IDENT: return "IDENT";
|
||||||
|
case INT: return "INT";
|
||||||
|
case FLOAT: return "FLOAT";
|
||||||
|
case CHAR: return "CHAR";
|
||||||
|
case STRING: return "STRING";
|
||||||
|
|
||||||
|
case ADD: return "+";
|
||||||
|
case SUB: return "-";
|
||||||
|
case MUL: return "*";
|
||||||
|
case QUO: return "/";
|
||||||
|
case REM: return "%";
|
||||||
|
|
||||||
|
case AND: return "&";
|
||||||
|
case OR: return "|";
|
||||||
|
case XOR: return "^";
|
||||||
|
case SHL: return "<<";
|
||||||
|
case SHR: return ">>";
|
||||||
|
|
||||||
|
case ADD_ASSIGN: return "+=";
|
||||||
|
case SUB_ASSIGN: return "-=";
|
||||||
|
case MUL_ASSIGN: return "+=";
|
||||||
|
case QUO_ASSIGN: return "/=";
|
||||||
|
case REM_ASSIGN: return "%=";
|
||||||
|
|
||||||
|
case AND_ASSIGN: return "&=";
|
||||||
|
case OR_ASSIGN: return "|=";
|
||||||
|
case XOR_ASSIGN: return "^=";
|
||||||
|
case SHL_ASSIGN: return "<<=";
|
||||||
|
case SHR_ASSIGN: return ">>=";
|
||||||
|
|
||||||
|
case LAND: return "&&";
|
||||||
|
case LOR: return "||";
|
||||||
|
case ARROW: return "<-";
|
||||||
|
case INC: return "++";
|
||||||
|
case DEC: return "--";
|
||||||
|
|
||||||
|
case EQL: return "==";
|
||||||
|
case LSS: return "<";
|
||||||
|
case GTR: return ">";
|
||||||
|
case ASSIGN: return "=";
|
||||||
|
case NOT: return "!";
|
||||||
|
|
||||||
|
case NEQ: return "!=";
|
||||||
|
case LEQ: return "<=";
|
||||||
|
case GEQ: return ">=";
|
||||||
|
case DEFINE: return ":=";
|
||||||
|
case ELLIPSIS: return "...";
|
||||||
|
|
||||||
|
case LPAREN: return "(";
|
||||||
|
case LBRACK: return "[";
|
||||||
|
case LBRACE: return "{";
|
||||||
|
case COMMA: return ",";
|
||||||
|
case PERIOD: return ".";
|
||||||
|
|
||||||
|
case RPAREN: return ")";
|
||||||
|
case RBRACK: return "]";
|
||||||
|
case RBRACE: return "}";
|
||||||
|
case SEMICOLON: return ";";
|
||||||
|
case COLON: return ":";
|
||||||
|
|
||||||
|
case BREAK: return "break";
|
||||||
|
case CASE: return "case";
|
||||||
|
case CHAN: return "chan";
|
||||||
|
case CONST: return "const";
|
||||||
|
case CONTINUE: return "continue";
|
||||||
|
|
||||||
|
case DEFAULT: return "default";
|
||||||
|
case DEFER: return "defer";
|
||||||
|
case ELSE: return "else";
|
||||||
|
case FALLTHROUGH: return "fallthrough";
|
||||||
|
case FOR: return "for";
|
||||||
|
|
||||||
|
case FUNC: return "func";
|
||||||
|
case GO: return "go";
|
||||||
|
case GOTO: return "goto";
|
||||||
|
case IF: return "if";
|
||||||
|
case IMPORT: return "import";
|
||||||
|
|
||||||
|
case INTERFACE: return "interface";
|
||||||
|
case MAP: return "map";
|
||||||
|
case PACKAGE: return "package";
|
||||||
|
case RANGE: return "range";
|
||||||
|
case RETURN: return "return";
|
||||||
|
|
||||||
|
case SELECT: return "select";
|
||||||
|
case STRUCT: return "struct";
|
||||||
|
case SWITCH: return "switch";
|
||||||
|
case TYPE: return "type";
|
||||||
|
case VAR: return "var";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "token(" + strconv.Itoa(tok) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const (
|
||||||
|
LowestPrec = -1;
|
||||||
|
UnaryPrec = 7;
|
||||||
|
HighestPrec = 8;
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func Precedence(tok int) int {
|
||||||
|
switch tok {
|
||||||
|
case COLON:
|
||||||
|
return 0;
|
||||||
|
case LOR:
|
||||||
|
return 1;
|
||||||
|
case LAND:
|
||||||
|
return 2;
|
||||||
|
case ARROW:
|
||||||
|
return 3;
|
||||||
|
case EQL, NEQ, LSS, LEQ, GTR, GEQ:
|
||||||
|
return 4;
|
||||||
|
case ADD, SUB, OR, XOR:
|
||||||
|
return 5;
|
||||||
|
case MUL, QUO, REM, SHL, SHR, AND:
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
return LowestPrec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var keywords map [string] int;
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
keywords = make(map [string] int);
|
||||||
|
for i := keyword_beg + 1; i < keyword_end; i++ {
|
||||||
|
keywords[TokenString(i)] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Map an identifier to its keyword token or IDENT (if not a keyword).
|
||||||
|
func Lookup(ident []byte) int {
|
||||||
|
// TODO should not have to convert every ident into a string
|
||||||
|
// for lookup - but at the moment maps of []byte don't
|
||||||
|
// seem to work - gri 3/3/09
|
||||||
|
if tok, is_keyword := keywords[string(ident)]; is_keyword {
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
return IDENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Predicates
|
||||||
|
|
||||||
|
// Identifiers and basic type literals
|
||||||
|
func IsLiteral(tok int) bool {
|
||||||
|
return literal_beg < tok && tok < literal_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Operators and delimiters
|
||||||
|
func IsOperator(tok int) bool {
|
||||||
|
return operator_beg < tok && tok < operator_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsKeyword(tok int) bool {
|
||||||
|
return keyword_beg < tok && tok < keyword_end;
|
||||||
|
}
|
@ -5,18 +5,23 @@
|
|||||||
package TypeChecker
|
package TypeChecker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"token";
|
||||||
AST "ast";
|
AST "ast";
|
||||||
Scanner "scanner";
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type ErrorHandler interface {
|
||||||
|
Error(pos int, msg string);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
type state struct {
|
type state struct {
|
||||||
// setup
|
// setup
|
||||||
err Scanner.ErrorHandler;
|
err ErrorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *state) Init(err Scanner.ErrorHandler) {
|
func (s *state) Init(err ErrorHandler) {
|
||||||
s.err = err;
|
s.err = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +59,7 @@ func (s *state) CheckType() {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
func (s *state) CheckDeclaration(d *AST.Decl) {
|
func (s *state) CheckDeclaration(d *AST.Decl) {
|
||||||
if d.Tok != Scanner.FUNC && d.List != nil {
|
if d.Tok != token.FUNC && d.List != nil {
|
||||||
// group of parenthesized declarations
|
// group of parenthesized declarations
|
||||||
for i := 0; i < d.List.Len(); i++ {
|
for i := 0; i < d.List.Len(); i++ {
|
||||||
s.CheckDeclaration(d.List.At(i).(*AST.Decl))
|
s.CheckDeclaration(d.List.At(i).(*AST.Decl))
|
||||||
@ -63,11 +68,11 @@ func (s *state) CheckDeclaration(d *AST.Decl) {
|
|||||||
} else {
|
} else {
|
||||||
// single declaration
|
// single declaration
|
||||||
switch d.Tok {
|
switch d.Tok {
|
||||||
case Scanner.IMPORT:
|
case token.IMPORT:
|
||||||
case Scanner.CONST:
|
case token.CONST:
|
||||||
case Scanner.VAR:
|
case token.VAR:
|
||||||
case Scanner.TYPE:
|
case token.TYPE:
|
||||||
case Scanner.FUNC:
|
case token.FUNC:
|
||||||
default:
|
default:
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
@ -85,7 +90,7 @@ func (s *state) CheckProgram(p *AST.Program) {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
func CheckProgram(err Scanner.ErrorHandler, p *AST.Program) {
|
func CheckProgram(err ErrorHandler, p *AST.Program) {
|
||||||
var s state;
|
var s state;
|
||||||
s.Init(err);
|
s.Init(err);
|
||||||
s.CheckProgram(p);
|
s.CheckProgram(p);
|
||||||
|
Loading…
Reference in New Issue
Block a user