tok int32
sym_ *Sym // valid if tok == LNAME
val Val // valid if tok == LLITERAL
- op Op // valid if tok == LASOP or LINCOP, or prec > 0
+ op Op // valid if tok == LOPER, LASOP, or LINCOP, or prec > 0
prec OpPrec // operator precedence; 0 if not a binary operator
}
const (
// The value of single-char tokens is just their character's Unicode value.
// They are all below utf8.RuneSelf. Shift other tokens up to avoid conflicts.
- LLITERAL = utf8.RuneSelf + iota
+
+ // names and literals
+ LNAME = utf8.RuneSelf + iota
+ LLITERAL
+
+ // operator-based operations
+ LOPER
LASOP
+ LINCOP
+
+ // miscellaneous
LCOLAS
+ LCOMM
+ LDDD
+
+ // keywords
LBREAK
LCASE
LCHAN
LCONST
LCONTINUE
- LDDD
LDEFAULT
LDEFER
LELSE
LIMPORT
LINTERFACE
LMAP
- LNAME
LPACKAGE
LRANGE
LRETURN
LSWITCH
LTYPE
LVAR
- LANDAND
- LANDNOT
- LCOMM
- LEQ
- LGE
- LGT
+
LIGNORE
- LINCOP
- LLE
- LLSH
- LLT
- LNE
- LOROR
- LRSH
)
func (l *lexer) next() {
goto incop
case '>':
+ c = LOPER
c1 = l.getr()
if c1 == '>' {
- c = LRSH
op = ORSH
prec = PMUL
goto binop
l.prec = PCMP
if c1 == '=' {
- c = LGE
l.op = OGE
goto lx
}
- c = LGT
l.op = OGT
case '<':
+ c = LOPER
c1 = l.getr()
if c1 == '<' {
- c = LLSH
op = OLSH
prec = PMUL
goto binop
l.prec = PCMP
if c1 == '=' {
- c = LLE
l.op = OLE
goto lx
}
- c = LLT
l.op = OLT
case '=':
c1 = l.getr()
if c1 == '=' {
- c = LEQ
+ c = LOPER
l.prec = PCMP
l.op = OEQ
goto lx
case '!':
c1 = l.getr()
if c1 == '=' {
- c = LNE
+ c = LOPER
l.prec = PCMP
l.op = ONE
goto lx
case '&':
c1 = l.getr()
if c1 == '&' {
- c = LANDAND
+ c = LOPER
l.prec = PANDAND
l.op = OANDAND
goto lx
}
if c1 == '^' {
- c = LANDNOT
+ c = LOPER
op = OANDNOT
prec = PMUL
goto binop
case '|':
c1 = l.getr()
if c1 == '|' {
- c = LOROR
+ c = LOPER
l.prec = POROR
l.op = OOROR
goto lx
}
var lexn = map[rune]string{
- LANDAND: "ANDAND",
- LANDNOT: "ANDNOT",
- LASOP: "ASOP",
+ LNAME: "NAME",
+ LLITERAL: "LITERAL",
+
+ LOPER: "OPER",
+ LASOP: "ASOP",
+ LINCOP: "INCOP",
+
+ LCOLAS: "COLAS",
+ LCOMM: "COMM",
+ LDDD: "DDD",
+
LBREAK: "BREAK",
LCASE: "CASE",
LCHAN: "CHAN",
- LCOLAS: "COLAS",
- LCOMM: "<-",
LCONST: "CONST",
LCONTINUE: "CONTINUE",
- LDDD: "...",
LDEFAULT: "DEFAULT",
LDEFER: "DEFER",
LELSE: "ELSE",
- LEQ: "EQ",
LFALL: "FALL",
LFOR: "FOR",
LFUNC: "FUNC",
- LGE: "GE",
LGO: "GO",
LGOTO: "GOTO",
- LGT: "GT",
LIF: "IF",
LIMPORT: "IMPORT",
- LINCOP: "INCOP",
LINTERFACE: "INTERFACE",
- LLE: "LE",
- LLITERAL: "LITERAL",
- LLSH: "LSH",
- LLT: "LT",
LMAP: "MAP",
- LNAME: "NAME",
- LNE: "NE",
- LOROR: "OROR",
LPACKAGE: "PACKAGE",
LRANGE: "RANGE",
LRETURN: "RETURN",
- LRSH: "RSH",
LSELECT: "SELECT",
LSTRUCT: "STRUCT",
LSWITCH: "SWITCH",
// determine token string
var tok string
switch p.tok {
- case LLITERAL:
- tok = litbuf
case LNAME:
if p.sym_ != nil && p.sym_.Name != "" {
tok = p.sym_.Name
} else {
tok = "name"
}
+ case LLITERAL:
+ tok = litbuf
+ case LOPER:
+ tok = goopnames[p.op]
case LASOP:
tok = goopnames[p.op] + "="
case LINCOP:
}
var tokstrings = map[int32]string{
- LLITERAL: "LLITERAL",
- LASOP: "op=",
- LCOLAS: ":=",
+ LNAME: "NAME",
+ LLITERAL: "LITERAL",
+
+ LOPER: "op",
+ LASOP: "op=",
+ LINCOP: "opop",
+
+ LCOLAS: ":=",
+ LCOMM: "<-",
+ LDDD: "...",
+
LBREAK: "break",
LCASE: "case",
LCHAN: "chan",
LCONST: "const",
LCONTINUE: "continue",
- LDDD: "...",
LDEFAULT: "default",
LDEFER: "defer",
LELSE: "else",
LIMPORT: "import",
LINTERFACE: "interface",
LMAP: "map",
- LNAME: "LNAME",
LPACKAGE: "package",
LRANGE: "range",
LRETURN: "return",
LSWITCH: "switch",
LTYPE: "type",
LVAR: "var",
- LANDAND: "&&",
- LANDNOT: "&^",
- LCOMM: "<-",
- LEQ: "==",
- LGE: ">=",
- LGT: ">",
- LIGNORE: "LIGNORE", // we should never see this one
- LINCOP: "opop",
- LLE: "<=",
- LLSH: "<<",
- LLT: "<",
- LNE: "!=",
- LOROR: "||",
- LRSH: ">>",
}
// usage: defer p.trace(msg)()