Home | History | Annotate | Download | only in lex
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package lex
      6 
      7 import (
      8 	"bytes"
      9 	"strings"
     10 	"testing"
     11 	"text/scanner"
     12 )
     13 
     14 type lexTest struct {
     15 	name   string
     16 	input  string
     17 	output string
     18 }
     19 
     20 var lexTests = []lexTest{
     21 	{
     22 		"empty",
     23 		"",
     24 		"",
     25 	},
     26 	{
     27 		"simple",
     28 		"1 (a)",
     29 		"1.(.a.)",
     30 	},
     31 	{
     32 		"simple define",
     33 		lines(
     34 			"#define A 1234",
     35 			"A",
     36 		),
     37 		"1234.\n",
     38 	},
     39 	{
     40 		"define without value",
     41 		"#define A",
     42 		"",
     43 	},
     44 	{
     45 		"macro without arguments",
     46 		"#define A() 1234\n" + "A()\n",
     47 		"1234.\n",
     48 	},
     49 	{
     50 		"macro with just parens as body",
     51 		"#define A () \n" + "A\n",
     52 		"(.).\n",
     53 	},
     54 	{
     55 		"macro with parens but no arguments",
     56 		"#define A (x) \n" + "A\n",
     57 		"(.x.).\n",
     58 	},
     59 	{
     60 		"macro with arguments",
     61 		"#define A(x, y, z) x+z+y\n" + "A(1, 2, 3)\n",
     62 		"1.+.3.+.2.\n",
     63 	},
     64 	{
     65 		"argumented macro invoked without arguments",
     66 		lines(
     67 			"#define X() foo ",
     68 			"X()",
     69 			"X",
     70 		),
     71 		"foo.\n.X.\n",
     72 	},
     73 	{
     74 		"multiline macro without arguments",
     75 		lines(
     76 			"#define A 1\\",
     77 			"\t2\\",
     78 			"\t3",
     79 			"before",
     80 			"A",
     81 			"after",
     82 		),
     83 		"before.\n.1.\n.2.\n.3.\n.after.\n",
     84 	},
     85 	{
     86 		"multiline macro with arguments",
     87 		lines(
     88 			"#define A(a, b, c) a\\",
     89 			"\tb\\",
     90 			"\tc",
     91 			"before",
     92 			"A(1, 2, 3)",
     93 			"after",
     94 		),
     95 		"before.\n.1.\n.2.\n.3.\n.after.\n",
     96 	},
     97 	{
     98 		"LOAD macro",
     99 		lines(
    100 			"#define LOAD(off, reg) \\",
    101 			"\tMOVBLZX	(off*4)(R12),	reg \\",
    102 			"\tADDB	reg,		DX",
    103 			"",
    104 			"LOAD(8, AX)",
    105 		),
    106 		"\n.\n.MOVBLZX.(.8.*.4.).(.R12.).,.AX.\n.ADDB.AX.,.DX.\n",
    107 	},
    108 	{
    109 		"nested multiline macro",
    110 		lines(
    111 			"#define KEYROUND(xmm, load, off, r1, r2, index) \\",
    112 			"\tMOVBLZX	(BP)(DX*4),	R8 \\",
    113 			"\tload((off+1), r2) \\",
    114 			"\tMOVB	R8,		(off*4)(R12) \\",
    115 			"\tPINSRW	$index, (BP)(R8*4), xmm",
    116 			"#define LOAD(off, reg) \\",
    117 			"\tMOVBLZX	(off*4)(R12),	reg \\",
    118 			"\tADDB	reg,		DX",
    119 			"KEYROUND(X0, LOAD, 8, AX, BX, 0)",
    120 		),
    121 		"\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",
    122 	},
    123 }
    124 
    125 func TestLex(t *testing.T) {
    126 	for _, test := range lexTests {
    127 		input := NewInput(test.name)
    128 		input.Push(NewTokenizer(test.name, strings.NewReader(test.input), nil))
    129 		result := drain(input)
    130 		if result != test.output {
    131 			t.Errorf("%s: got %q expected %q", test.name, result, test.output)
    132 		}
    133 	}
    134 }
    135 
    136 // lines joins the arguments together as complete lines.
    137 func lines(a ...string) string {
    138 	return strings.Join(a, "\n") + "\n"
    139 }
    140 
    141 // drain returns a single string representing the processed input tokens.
    142 func drain(input *Input) string {
    143 	var buf bytes.Buffer
    144 	for {
    145 		tok := input.Next()
    146 		if tok == scanner.EOF {
    147 			return buf.String()
    148 		}
    149 		if buf.Len() > 0 {
    150 			buf.WriteByte('.')
    151 		}
    152 		buf.WriteString(input.Text())
    153 	}
    154 }
    155