mirror of
https://github.com/golang/go
synced 2024-11-19 09:04:41 -07:00
[dev.cc] cmd/asm: fix macro definition bug in the lexer
Because text/scanner hides the spaces, the lexer treated #define A(x) and #define A (x) the same, but they are not: the first is an argument with macros, the second is a simple one-word macro whose definition contains parentheses. Fix this by noticing the relative column number as we move from A to (. Hacky but simple. Also add a helper to recognize the peculiar ARM shifted register operators. Change-Id: I2cad22f5f1e11d8dad40ad13955793d178afb3ae Reviewed-on: https://go-review.googlesource.com/4872 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
7fbfbca2c4
commit
ae2b145da2
@ -203,12 +203,21 @@ func (in *Input) defineMacro(name string, args []string, tokens []Token) {
|
|||||||
// The argument list is nil for no parens on the definition; otherwise a list of
|
// The argument list is nil for no parens on the definition; otherwise a list of
|
||||||
// formal argument names.
|
// formal argument names.
|
||||||
func (in *Input) macroDefinition(name string) ([]string, []Token) {
|
func (in *Input) macroDefinition(name string) ([]string, []Token) {
|
||||||
|
prevCol := in.Stack.Col()
|
||||||
tok := in.Stack.Next()
|
tok := in.Stack.Next()
|
||||||
if tok == '\n' || tok == scanner.EOF {
|
if tok == '\n' || tok == scanner.EOF {
|
||||||
in.Error("no definition for macro:", name)
|
in.Error("no definition for macro:", name)
|
||||||
}
|
}
|
||||||
var args []string
|
var args []string
|
||||||
if tok == '(' {
|
// The C preprocessor treats
|
||||||
|
// #define A(x)
|
||||||
|
// and
|
||||||
|
// #define A (x)
|
||||||
|
// distinctly: the first is a macro with arguments, the second without.
|
||||||
|
// Distinguish these cases using the column number, since we don't
|
||||||
|
// see the space itself. Note that text/scanner reports the position at the
|
||||||
|
// end of the token. It's where you are now, and you just read this token.
|
||||||
|
if tok == '(' && in.Stack.Col() == prevCol+1 {
|
||||||
// Macro has arguments. Scan list of formals.
|
// Macro has arguments. Scan list of formals.
|
||||||
acceptArg := true
|
acceptArg := true
|
||||||
args = []string{} // Zero length but not nil.
|
args = []string{} // Zero length but not nil.
|
||||||
|
@ -29,6 +29,11 @@ const (
|
|||||||
macroName // name of macro that should not be expanded
|
macroName // name of macro that should not be expanded
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// IsRegisterShift reports whether the token is one of the ARM register shift operators.
|
||||||
|
func IsRegisterShift(r ScanToken) bool {
|
||||||
|
return ROT <= r && r <= LSH // Order looks backwards because these are negative.
|
||||||
|
}
|
||||||
|
|
||||||
func (t ScanToken) String() string {
|
func (t ScanToken) String() string {
|
||||||
switch t {
|
switch t {
|
||||||
case scanner.EOF:
|
case scanner.EOF:
|
||||||
@ -94,6 +99,8 @@ type TokenReader interface {
|
|||||||
File() string
|
File() string
|
||||||
// Line reports the source line number of the token.
|
// Line reports the source line number of the token.
|
||||||
Line() int
|
Line() int
|
||||||
|
// Col reports the source column number of the token.
|
||||||
|
Col() int
|
||||||
// SetPos sets the file and line number.
|
// SetPos sets the file and line number.
|
||||||
SetPos(line int, file string)
|
SetPos(line int, file string)
|
||||||
// Close does any teardown required.
|
// Close does any teardown required.
|
||||||
|
@ -41,6 +41,16 @@ var lexTests = []lexTest{
|
|||||||
"#define A() 1234\n" + "A()\n",
|
"#define A() 1234\n" + "A()\n",
|
||||||
"1234.\n",
|
"1234.\n",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"macro with just parens as body",
|
||||||
|
"#define A () \n" + "A\n",
|
||||||
|
"(.).\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"macro with parens but no arguments",
|
||||||
|
"#define A (x) \n" + "A\n",
|
||||||
|
"(.x.).\n",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"macro with arguments",
|
"macro with arguments",
|
||||||
"#define A(x, y, z) x+z+y\n" + "A(1, 2, 3)\n",
|
"#define A(x, y, z) x+z+y\n" + "A(1, 2, 3)\n",
|
||||||
|
@ -43,6 +43,11 @@ func (s *Slice) Line() int {
|
|||||||
return s.line
|
return s.line
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Slice) Col() int {
|
||||||
|
// Col is only called when defining a macro, which can't reach here.
|
||||||
|
panic("cannot happen: slice col")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Slice) SetPos(line int, file string) {
|
func (s *Slice) SetPos(line int, file string) {
|
||||||
// Cannot happen because we only have slices of already-scanned
|
// Cannot happen because we only have slices of already-scanned
|
||||||
// text, but be prepared.
|
// text, but be prepared.
|
||||||
|
@ -41,6 +41,10 @@ func (s *Stack) Line() int {
|
|||||||
return s.tr[len(s.tr)-1].Line()
|
return s.tr[len(s.tr)-1].Line()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Stack) Col() int {
|
||||||
|
return s.tr[len(s.tr)-1].Col()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Stack) SetPos(line int, file string) {
|
func (s *Stack) SetPos(line int, file string) {
|
||||||
s.tr[len(s.tr)-1].SetPos(line, file)
|
s.tr[len(s.tr)-1].SetPos(line, file)
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,10 @@ func (t *Tokenizer) Line() int {
|
|||||||
return t.line
|
return t.line
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tokenizer) Col() int {
|
||||||
|
return t.s.Pos().Column
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tokenizer) SetPos(line int, file string) {
|
func (t *Tokenizer) SetPos(line int, file string) {
|
||||||
t.line = line
|
t.line = line
|
||||||
t.fileName = file
|
t.fileName = file
|
||||||
|
Loading…
Reference in New Issue
Block a user