mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
149 lines
2.8 KiB
Go
149 lines
2.8 KiB
Go
// Copyright 2015 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 lex
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
"testing"
|
|
"text/scanner"
|
|
)
|
|
|
|
type lexTest struct {
|
|
name string
|
|
input string
|
|
output string
|
|
}
|
|
|
|
var lexTests = []lexTest{
|
|
{
|
|
"empty",
|
|
"",
|
|
"",
|
|
},
|
|
{
|
|
"simple",
|
|
"1 (a)",
|
|
"1.(.a.)",
|
|
},
|
|
{
|
|
"simple define",
|
|
lines(
|
|
"#define A 1234",
|
|
"A",
|
|
),
|
|
"1234.\n",
|
|
},
|
|
{
|
|
"macro without arguments",
|
|
"#define A() 1234\n" + "A()\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",
|
|
"#define A(x, y, z) x+z+y\n" + "A(1, 2, 3)\n",
|
|
"1.+.3.+.2.\n",
|
|
},
|
|
{
|
|
"argumented macro invoked without arguments",
|
|
lines(
|
|
"#define X() foo ",
|
|
"X()",
|
|
"X",
|
|
),
|
|
"foo.\n.X.\n",
|
|
},
|
|
{
|
|
"multiline macro without arguments",
|
|
lines(
|
|
"#define A 1\\",
|
|
"\t2\\",
|
|
"\t3",
|
|
"before",
|
|
"A",
|
|
"after",
|
|
),
|
|
"before.\n.1.\n.2.\n.3.\n.after.\n",
|
|
},
|
|
{
|
|
"multiline macro with arguments",
|
|
lines(
|
|
"#define A(a, b, c) a\\",
|
|
"\tb\\",
|
|
"\tc",
|
|
"before",
|
|
"A(1, 2, 3)",
|
|
"after",
|
|
),
|
|
"before.\n.1.\n.2.\n.3.\n.after.\n",
|
|
},
|
|
{
|
|
"LOAD macro",
|
|
lines(
|
|
"#define LOAD(off, reg) \\",
|
|
"\tMOVBLZX (off*4)(R12), reg \\",
|
|
"\tADDB reg, DX",
|
|
"",
|
|
"LOAD(8, AX)",
|
|
),
|
|
"\n.\n.MOVBLZX.(.8.*.4.).(.R12.).,.AX.\n.ADDB.AX.,.DX.\n",
|
|
},
|
|
{
|
|
"nested multiline macro",
|
|
lines(
|
|
"#define KEYROUND(xmm, load, off, r1, r2, index) \\",
|
|
"\tMOVBLZX (BP)(DX*4), R8 \\",
|
|
"\tload((off+1), r2) \\",
|
|
"\tMOVB R8, (off*4)(R12) \\",
|
|
"\tPINSRW $index, (BP)(R8*4), xmm",
|
|
"#define LOAD(off, reg) \\",
|
|
"\tMOVBLZX (off*4)(R12), reg \\",
|
|
"\tADDB reg, DX",
|
|
"KEYROUND(X0, LOAD, 8, AX, BX, 0)",
|
|
),
|
|
"\n.MOVBLZX.(.BP.).(.DX.*.4.).,.R8.\n.\n.MOVBLZX.(.(.8.+.1.).*.4.).(.R12.).,.BX.\n.ADDB.BX.,.DX.\n.MOVB.R8.,.(.8.*.4.).(.R12.).\n.PINSRW.$.0.,.(.BP.).(.R8.*.4.).,.X0.\n",
|
|
},
|
|
}
|
|
|
|
func TestLex(t *testing.T) {
|
|
for _, test := range lexTests {
|
|
input := NewInput(test.name)
|
|
input.Push(NewTokenizer(test.name, strings.NewReader(test.input), nil))
|
|
result := drain(input)
|
|
if result != test.output {
|
|
t.Errorf("%s: got %q expected %q", test.name, result, test.output)
|
|
}
|
|
}
|
|
}
|
|
|
|
// lines joins the arguments together as complete lines.
|
|
func lines(a ...string) string {
|
|
return strings.Join(a, "\n") + "\n"
|
|
}
|
|
|
|
// drain returns a single string representing the processed input tokens.
|
|
func drain(input *Input) string {
|
|
var buf bytes.Buffer
|
|
for {
|
|
tok := input.Next()
|
|
if tok == scanner.EOF {
|
|
return buf.String()
|
|
}
|
|
if buf.Len() > 0 {
|
|
buf.WriteByte('.')
|
|
}
|
|
buf.WriteString(input.Text())
|
|
}
|
|
}
|