Commit f5f8b384 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: eliminate prectab

While here, merge LINC and LDEC into LINCOP.

Fixes #13244.

Change-Id: I8ea426f986d60d35c3b1a80c056a7aa49d22d802
Reviewed-on: https://go-review.googlesource.com/19928Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 6abc8c9a
...@@ -871,11 +871,24 @@ type lexer struct { ...@@ -871,11 +871,24 @@ type lexer struct {
// current token // current token
tok int32 tok int32
sym_ *Sym // valid if tok == LNAME sym_ *Sym // valid if tok == LNAME
val Val // valid if tok == LLITERAL val Val // valid if tok == LLITERAL
op Op // valid if tok == LASOP op Op // valid if tok == LASOP or LINCOP, or prec > 0
prec OpPrec // operator precedence; 0 if not a binary operator
} }
type OpPrec int
const (
// Precedences of binary operators (must be > 0).
PCOMM OpPrec = 1 + iota
POROR
PANDAND
PCMP
PADD
PMUL
)
const ( const (
// The value of single-char tokens is just their character's Unicode value. // 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. // They are all below utf8.RuneSelf. Shift other tokens up to avoid conflicts.
...@@ -912,12 +925,11 @@ const ( ...@@ -912,12 +925,11 @@ const (
LANDAND LANDAND
LANDNOT LANDNOT
LCOMM LCOMM
LDEC
LEQ LEQ
LGE LGE
LGT LGT
LIGNORE LIGNORE
LINC LINCOP
LLE LLE
LLSH LLSH
LLT LLT
...@@ -929,6 +941,7 @@ const ( ...@@ -929,6 +941,7 @@ const (
func (l *lexer) next() { func (l *lexer) next() {
nlsemi := l.nlsemi nlsemi := l.nlsemi
l.nlsemi = false l.nlsemi = false
l.prec = 0
l0: l0:
// skip white space // skip white space
...@@ -963,6 +976,7 @@ l0: ...@@ -963,6 +976,7 @@ l0:
var c1 rune var c1 rune
var op Op var op Op
var prec OpPrec
switch c { switch c {
case EOF: case EOF:
...@@ -1056,10 +1070,9 @@ l0: ...@@ -1056,10 +1070,9 @@ l0:
} }
} }
if c1 == '=' { op = ODIV
op = ODIV prec = PMUL
goto asop goto binop1
}
case ':': case ':':
c1 = l.getr() c1 = l.getr()
...@@ -1069,94 +1082,75 @@ l0: ...@@ -1069,94 +1082,75 @@ l0:
} }
case '*': case '*':
c1 = l.getr() op = OMUL
if c1 == '=' { prec = PMUL
op = OMUL goto binop
goto asop
}
case '%': case '%':
c1 = l.getr() op = OMOD
if c1 == '=' { prec = PMUL
op = OMOD goto binop
goto asop
}
case '+': case '+':
c1 = l.getr() op = OADD
if c1 == '+' { goto incop
l.nlsemi = true
c = LINC
goto lx
}
if c1 == '=' {
op = OADD
goto asop
}
case '-': case '-':
c1 = l.getr() op = OSUB
if c1 == '-' { goto incop
l.nlsemi = true
c = LDEC
goto lx
}
if c1 == '=' {
op = OSUB
goto asop
}
case '>': case '>':
c1 = l.getr() c1 = l.getr()
if c1 == '>' { if c1 == '>' {
c = LRSH c = LRSH
c1 = l.getr() op = ORSH
if c1 == '=' { prec = PMUL
op = ORSH goto binop
goto asop
}
break
} }
l.prec = PCMP
if c1 == '=' { if c1 == '=' {
c = LGE c = LGE
l.op = OGE
goto lx goto lx
} }
c = LGT c = LGT
l.op = OGT
case '<': case '<':
c1 = l.getr() c1 = l.getr()
if c1 == '<' { if c1 == '<' {
c = LLSH c = LLSH
c1 = l.getr() op = OLSH
if c1 == '=' { prec = PMUL
op = OLSH goto binop
goto asop
}
break
}
if c1 == '=' {
c = LLE
goto lx
} }
if c1 == '-' { if c1 == '-' {
c = LCOMM c = LCOMM
// Not a binary operator, but parsed as one
// so we can give a good error message when used
// in an expression context.
l.prec = PCOMM
l.op = OSEND
goto lx goto lx
} }
l.prec = PCMP
if c1 == '=' {
c = LLE
l.op = OLE
goto lx
}
c = LLT c = LLT
l.op = OLT
case '=': case '=':
c1 = l.getr() c1 = l.getr()
if c1 == '=' { if c1 == '=' {
c = LEQ c = LEQ
l.prec = PCMP
l.op = OEQ
goto lx goto lx
} }
...@@ -1164,6 +1158,8 @@ l0: ...@@ -1164,6 +1158,8 @@ l0:
c1 = l.getr() c1 = l.getr()
if c1 == '=' { if c1 == '=' {
c = LNE c = LNE
l.prec = PCMP
l.op = ONE
goto lx goto lx
} }
...@@ -1171,43 +1167,39 @@ l0: ...@@ -1171,43 +1167,39 @@ l0:
c1 = l.getr() c1 = l.getr()
if c1 == '&' { if c1 == '&' {
c = LANDAND c = LANDAND
l.prec = PANDAND
l.op = OANDAND
goto lx goto lx
} }
if c1 == '^' { if c1 == '^' {
c = LANDNOT c = LANDNOT
c1 = l.getr() op = OANDNOT
if c1 == '=' { prec = PMUL
op = OANDNOT goto binop
goto asop
}
break
} }
if c1 == '=' { op = OAND
op = OAND prec = PMUL
goto asop goto binop1
}
case '|': case '|':
c1 = l.getr() c1 = l.getr()
if c1 == '|' { if c1 == '|' {
c = LOROR c = LOROR
l.prec = POROR
l.op = OOROR
goto lx goto lx
} }
if c1 == '=' { op = OOR
op = OOR prec = PADD
goto asop goto binop1
}
case '^': case '^':
c1 = l.getr() op = OXOR
if c1 == '=' { prec = PADD
op = OXOR goto binop
goto asop
}
case '(', '[', '{', ',', ';': case '(', '[', '{', ',', ';':
goto lx goto lx
...@@ -1232,7 +1224,7 @@ l0: ...@@ -1232,7 +1224,7 @@ l0:
lx: lx:
if Debug['x'] != 0 { if Debug['x'] != 0 {
if c > 0xff { if c >= utf8.RuneSelf {
fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lineno)), lexname(c)) fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lineno)), lexname(c))
} else { } else {
fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lineno)), c) fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lineno)), c)
...@@ -1242,7 +1234,27 @@ lx: ...@@ -1242,7 +1234,27 @@ lx:
l.tok = c l.tok = c
return return
asop: incop:
c1 = l.getr()
if c1 == c {
l.nlsemi = true
l.op = op
c = LINCOP
goto lx
}
prec = PADD
goto binop1
binop:
c1 = l.getr()
binop1:
if c1 != '=' {
l.ungetr(c1)
l.op = op
l.prec = prec
goto lx
}
l.op = op l.op = op
if Debug['x'] != 0 { if Debug['x'] != 0 {
fmt.Printf("lex: TOKEN ASOP %s=\n", goopnames[op]) fmt.Printf("lex: TOKEN ASOP %s=\n", goopnames[op])
...@@ -2319,7 +2331,6 @@ var lexn = map[rune]string{ ...@@ -2319,7 +2331,6 @@ var lexn = map[rune]string{
LCONST: "CONST", LCONST: "CONST",
LCONTINUE: "CONTINUE", LCONTINUE: "CONTINUE",
LDDD: "...", LDDD: "...",
LDEC: "DEC",
LDEFAULT: "DEFAULT", LDEFAULT: "DEFAULT",
LDEFER: "DEFER", LDEFER: "DEFER",
LELSE: "ELSE", LELSE: "ELSE",
...@@ -2333,7 +2344,7 @@ var lexn = map[rune]string{ ...@@ -2333,7 +2344,7 @@ var lexn = map[rune]string{
LGT: "GT", LGT: "GT",
LIF: "IF", LIF: "IF",
LIMPORT: "IMPORT", LIMPORT: "IMPORT",
LINC: "INC", LINCOP: "INCOP",
LINTERFACE: "INTERFACE", LINTERFACE: "INTERFACE",
LLE: "LE", LLE: "LE",
LLITERAL: "LITERAL", LLITERAL: "LITERAL",
......
...@@ -102,6 +102,8 @@ func (p *parser) syntax_error(msg string) { ...@@ -102,6 +102,8 @@ func (p *parser) syntax_error(msg string) {
} }
case LASOP: case LASOP:
tok = goopnames[p.op] + "=" tok = goopnames[p.op] + "="
case LINCOP:
tok = goopnames[p.op] + goopnames[p.op]
default: default:
tok = tokstring(p.tok) tok = tokstring(p.tok)
} }
...@@ -219,12 +221,11 @@ var tokstrings = map[int32]string{ ...@@ -219,12 +221,11 @@ var tokstrings = map[int32]string{
LANDAND: "&&", LANDAND: "&&",
LANDNOT: "&^", LANDNOT: "&^",
LCOMM: "<-", LCOMM: "<-",
LDEC: "--",
LEQ: "==", LEQ: "==",
LGE: ">=", LGE: ">=",
LGT: ">", LGT: ">",
LIGNORE: "LIGNORE", // we should never see this one LIGNORE: "LIGNORE", // we should never see this one
LINC: "++", LINCOP: "opop",
LLE: "<=", LLE: "<=",
LLSH: "<<", LLSH: "<<",
LLT: "<", LLT: "<",
...@@ -562,22 +563,13 @@ func (p *parser) simple_stmt(labelOk, rangeOk bool) *Node { ...@@ -562,22 +563,13 @@ func (p *parser) simple_stmt(labelOk, rangeOk bool) *Node {
stmt.Etype = EType(op) // rathole to pass opcode stmt.Etype = EType(op) // rathole to pass opcode
return stmt return stmt
case LINC: case LINCOP:
// expr LINC // expr LINCOP
p.next() p.next()
stmt := Nod(OASOP, lhs, Nodintconst(1)) stmt := Nod(OASOP, lhs, Nodintconst(1))
stmt.Implicit = true stmt.Implicit = true
stmt.Etype = EType(OADD) stmt.Etype = EType(p.op)
return stmt
case LDEC:
// expr LDEC
p.next()
stmt := Nod(OASOP, lhs, Nodintconst(1))
stmt.Implicit = true
stmt.Etype = EType(OSUB)
return stmt return stmt
case ':': case ':':
...@@ -1104,54 +1096,20 @@ func (p *parser) select_stmt() *Node { ...@@ -1104,54 +1096,20 @@ func (p *parser) select_stmt() *Node {
return hdr return hdr
} }
// TODO(gri) should have lexer return this info - no need for separate lookup
// (issue 13244)
var prectab = map[int32]struct {
prec int // > 0 (0 indicates not found)
op Op
}{
// not an expression anymore, but left in so we can give a good error
// message when used in expression context
LCOMM: {1, OSEND},
LOROR: {2, OOROR},
LANDAND: {3, OANDAND},
LEQ: {4, OEQ},
LNE: {4, ONE},
LLE: {4, OLE},
LGE: {4, OGE},
LLT: {4, OLT},
LGT: {4, OGT},
'+': {5, OADD},
'-': {5, OSUB},
'|': {5, OOR},
'^': {5, OXOR},
'*': {6, OMUL},
'/': {6, ODIV},
'%': {6, OMOD},
'&': {6, OAND},
LLSH: {6, OLSH},
LRSH: {6, ORSH},
LANDNOT: {6, OANDNOT},
}
// Expression = UnaryExpr | Expression binary_op Expression . // Expression = UnaryExpr | Expression binary_op Expression .
func (p *parser) bexpr(prec int) *Node { func (p *parser) bexpr(prec OpPrec) *Node {
// don't trace bexpr - only leads to overly nested trace output // don't trace bexpr - only leads to overly nested trace output
// prec is precedence of the prior/enclosing binary operator (if any),
// so we only want to parse tokens of greater precedence.
x := p.uexpr() x := p.uexpr()
for { for p.prec > prec {
t := prectab[p.tok] op, prec1 := p.op, p.prec
if t.prec < prec {
return x
}
p.next() p.next()
x = Nod(t.op, x, p.bexpr(t.prec+1)) x = Nod(op, x, p.bexpr(prec1))
} }
return x
} }
func (p *parser) expr() *Node { func (p *parser) expr() *Node {
...@@ -1159,7 +1117,7 @@ func (p *parser) expr() *Node { ...@@ -1159,7 +1117,7 @@ func (p *parser) expr() *Node {
defer p.trace("expr")() defer p.trace("expr")()
} }
return p.bexpr(1) return p.bexpr(0)
} }
func unparen(x *Node) *Node { func unparen(x *Node) *Node {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment