blob: fdc884bcf6f79cbd15e2a77ddebdab5fd12d301c [file] [log] [blame]
Ben Clayton6cf2fd42021-05-31 09:48:48 +00001// Copyright 2021 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package parser_test
16
17import (
18 "testing"
19
20 "dawn.googlesource.com/tint/tools/src/cmd/intrinsic-gen/ast"
21 "dawn.googlesource.com/tint/tools/src/cmd/intrinsic-gen/parser"
22)
23
24func TestParser(t *testing.T) {
25 type test struct {
26 src string
27 expect ast.AST
28 }
29
30 for _, test := range []test{
31 {"enum E {}", ast.AST{
32 Enums: []ast.EnumDecl{{Name: "E"}},
33 }},
Ben Clayton04bd2e82021-06-03 08:42:14 +000034 {"enum E { A [[deco]] B C }", ast.AST{
Ben Clayton6cf2fd42021-05-31 09:48:48 +000035 Enums: []ast.EnumDecl{{
Ben Clayton04bd2e82021-06-03 08:42:14 +000036 Name: "E",
37 Entries: []ast.EnumEntry{
38 {Name: "A"},
39 {
40 Decorations: ast.Decorations{{Name: "deco"}},
41 Name: "B",
42 },
43 {Name: "C"},
44 },
Ben Clayton6cf2fd42021-05-31 09:48:48 +000045 }},
46 }},
47 {"type T", ast.AST{
48 Types: []ast.TypeDecl{{Name: "T"}},
49 }},
50 {"type T<A, B, C>", ast.AST{
51 Types: []ast.TypeDecl{{
52 Name: "T",
53 TemplateParams: ast.TemplateParams{
54 {Name: "A"},
55 {Name: "B"},
56 {Name: "C"},
57 },
58 }},
59 }},
60 {"[[deco]] type T", ast.AST{
61 Types: []ast.TypeDecl{{
62 Decorations: ast.Decorations{
63 {Name: "deco"},
64 },
65 Name: "T",
66 }},
67 }},
68 {`[[deco("a", "b")]] type T`, ast.AST{
69 Types: []ast.TypeDecl{{
70 Decorations: ast.Decorations{
71 {Name: "deco", Values: []string{"a", "b"}},
72 },
73 Name: "T",
74 }},
75 }},
76 {"match M : A", ast.AST{
77 Matchers: []ast.MatcherDecl{{
78 Name: "M",
79 Options: ast.MatcherOptions{
80 ast.TemplatedName{Name: "A"},
81 },
82 }},
83 }},
84 {"match M : A | B", ast.AST{
85 Matchers: []ast.MatcherDecl{{
86 Name: "M",
87 Options: ast.MatcherOptions{
88 ast.TemplatedName{Name: "A"},
89 ast.TemplatedName{Name: "B"},
90 },
91 }},
92 }},
93 {"fn F()", ast.AST{
94 Functions: []ast.FunctionDecl{{
95 Name: "F",
96 }},
97 }},
Ben Clayton194c58f2021-06-03 09:53:34 +000098 {"[[deco]] fn F()", ast.AST{
99 Functions: []ast.FunctionDecl{{
100 Name: "F",
101 Decorations: ast.Decorations{
102 {Name: "deco"},
103 },
104 }},
105 }},
Ben Clayton6cf2fd42021-05-31 09:48:48 +0000106 {"fn F(a)", ast.AST{
107 Functions: []ast.FunctionDecl{{
108 Name: "F",
109 Parameters: ast.Parameters{
110 {Type: ast.TemplatedName{Name: "a"}},
111 },
112 }},
113 }},
Ben Clayton126adb12021-06-01 09:07:10 +0000114 {"fn F(a: T)", ast.AST{
Ben Clayton6cf2fd42021-05-31 09:48:48 +0000115 Functions: []ast.FunctionDecl{{
116 Name: "F",
117 Parameters: ast.Parameters{
118 {Name: "a", Type: ast.TemplatedName{Name: "T"}},
119 },
120 }},
121 }},
122 {"fn F(a, b)", ast.AST{
123 Functions: []ast.FunctionDecl{{
124 Name: "F",
125 Parameters: ast.Parameters{
126 {Type: ast.TemplatedName{Name: "a"}},
127 {Type: ast.TemplatedName{Name: "b"}},
128 },
129 }},
130 }},
131 {"fn F<A : B<C>>()", ast.AST{
132 Functions: []ast.FunctionDecl{{
133 Name: "F",
134 TemplateParams: ast.TemplateParams{
135 {
136 Name: "A", Type: ast.TemplatedName{
137 Name: "B",
138 TemplateArgs: ast.TemplatedNames{
139 {Name: "C"},
140 },
141 },
142 },
143 },
144 }},
145 }},
Ben Clayton126adb12021-06-01 09:07:10 +0000146 {"fn F<T>(a: X, b: Y<T>)", ast.AST{
Ben Clayton6cf2fd42021-05-31 09:48:48 +0000147 Functions: []ast.FunctionDecl{{
148 Name: "F",
149 TemplateParams: ast.TemplateParams{
150 {Name: "T"},
151 },
152 Parameters: ast.Parameters{
153 {Name: "a", Type: ast.TemplatedName{Name: "X"}},
154 {Name: "b", Type: ast.TemplatedName{
155 Name: "Y",
156 TemplateArgs: []ast.TemplatedName{{Name: "T"}},
157 }},
158 },
159 }},
160 }},
161 {"fn F() -> X", ast.AST{
162 Functions: []ast.FunctionDecl{{
163 Name: "F",
164 ReturnType: &ast.TemplatedName{Name: "X"},
165 }},
166 }},
167 {"fn F() -> X<T>", ast.AST{
168 Functions: []ast.FunctionDecl{{
169 Name: "F",
170 ReturnType: &ast.TemplatedName{
171 Name: "X",
172 TemplateArgs: []ast.TemplatedName{{Name: "T"}},
173 },
174 }},
175 }},
176 } {
177 got, err := parser.Parse(test.src, "file.txt")
178 if err != nil {
179 t.Errorf("While parsing:\n%s\nParse() returned error: %v", test.src, err)
180 continue
181 }
182
183 gotStr, expectStr := got.String(), test.expect.String()
184 if gotStr != expectStr {
185 t.Errorf("While parsing:\n%s\nGot:\n%s\nExpected:\n%s", test.src, gotStr, expectStr)
186 }
187 }
188}
189
190func TestErrors(t *testing.T) {
191 type test struct {
192 src string
193 expect string
194 }
195
196 for _, test := range []test{
197 {"+", "test.txt:1:1: unexpected '+'"},
198 {"123", "test.txt:1:1 unexpected token 'integer'"},
199 {"[[123]]", "test.txt:1:3 expected 'ident' for decoration name, got 'integer'"},
200 {"[[abc", "expected ']]' for decoration list, but reached end of file"},
201 } {
202 got, err := parser.Parse(test.src, "test.txt")
203 if gotErr := err.Error(); test.expect != gotErr {
204 t.Errorf(`Parse() returned error "%+v", expected error "%+v"`, gotErr, test.expect)
205 }
206 if got != nil {
207 t.Errorf("Lex() returned non-nil for error")
208 }
209 }
210}