mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-18 17:35:30 +00:00
tools: Shuffle 'intrinsic-gen' tooling
Rename to 'gen', so that more templating can be added without having a confusing name. Can now be run with './tools/run gen' Move the bulk of the intrinsic-gen logic to `tools/src/tint/intrinsic` Change-Id: I750989a5aa86272c10c2ad37adffe7def11c61f2 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97141 Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
62c58a076c
commit
cde5009be3
376
tools/src/tint/intrinsic/parser/parser.go
Normal file
376
tools/src/tint/intrinsic/parser/parser.go
Normal file
@@ -0,0 +1,376 @@
|
||||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package parser provides a basic parser for the Tint builtin definition
|
||||
// language
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/ast"
|
||||
"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/lexer"
|
||||
"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/tok"
|
||||
)
|
||||
|
||||
// Parse produces a list of tokens for the given source code
|
||||
func Parse(source, filepath string) (*ast.AST, error) {
|
||||
runes := []rune(source)
|
||||
tokens, err := lexer.Lex(runes, filepath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := parser{tokens: tokens}
|
||||
return p.parse()
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
tokens []tok.Token
|
||||
err error
|
||||
}
|
||||
|
||||
func (p *parser) parse() (*ast.AST, error) {
|
||||
out := ast.AST{}
|
||||
var attributes ast.Attributes
|
||||
for p.err == nil {
|
||||
t := p.peek(0)
|
||||
if t == nil {
|
||||
break
|
||||
}
|
||||
switch t.Kind {
|
||||
case tok.Attr:
|
||||
attributes = append(attributes, p.attributes()...)
|
||||
case tok.Enum:
|
||||
if len(attributes) > 0 {
|
||||
p.err = fmt.Errorf("%v unexpected attribute", attributes[0].Source)
|
||||
}
|
||||
out.Enums = append(out.Enums, p.enumDecl())
|
||||
case tok.Match:
|
||||
if len(attributes) > 0 {
|
||||
p.err = fmt.Errorf("%v unexpected attribute", attributes[0].Source)
|
||||
}
|
||||
out.Matchers = append(out.Matchers, p.matcherDecl())
|
||||
case tok.Type:
|
||||
out.Types = append(out.Types, p.typeDecl(attributes))
|
||||
attributes = nil
|
||||
case tok.Function:
|
||||
out.Builtins = append(out.Builtins, p.builtinDecl(attributes))
|
||||
attributes = nil
|
||||
case tok.Operator:
|
||||
out.Operators = append(out.Operators, p.operatorDecl(attributes))
|
||||
attributes = nil
|
||||
case tok.Constructor:
|
||||
out.Constructors = append(out.Constructors, p.constructorDecl(attributes))
|
||||
attributes = nil
|
||||
case tok.Converter:
|
||||
out.Converters = append(out.Converters, p.converterDecl(attributes))
|
||||
attributes = nil
|
||||
default:
|
||||
p.err = fmt.Errorf("%v unexpected token '%v'", t.Source, t.Kind)
|
||||
}
|
||||
if p.err != nil {
|
||||
return nil, p.err
|
||||
}
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (p *parser) enumDecl() ast.EnumDecl {
|
||||
p.expect(tok.Enum, "enum declaration")
|
||||
name := p.expect(tok.Identifier, "enum name")
|
||||
e := ast.EnumDecl{Source: name.Source, Name: string(name.Runes)}
|
||||
p.expect(tok.Lbrace, "enum declaration")
|
||||
for p.err == nil && p.match(tok.Rbrace) == nil {
|
||||
e.Entries = append(e.Entries, p.enumEntry())
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (p *parser) enumEntry() ast.EnumEntry {
|
||||
decos := p.attributes()
|
||||
name := p.expect(tok.Identifier, "enum entry")
|
||||
return ast.EnumEntry{Source: name.Source, Attributes: decos, Name: string(name.Runes)}
|
||||
}
|
||||
|
||||
func (p *parser) matcherDecl() ast.MatcherDecl {
|
||||
p.expect(tok.Match, "matcher declaration")
|
||||
name := p.expect(tok.Identifier, "matcher name")
|
||||
m := ast.MatcherDecl{Source: name.Source, Name: string(name.Runes)}
|
||||
p.expect(tok.Colon, "matcher declaration")
|
||||
for p.err == nil {
|
||||
m.Options = append(m.Options, p.templatedName())
|
||||
if p.match(tok.Or) == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (p *parser) typeDecl(decos ast.Attributes) ast.TypeDecl {
|
||||
p.expect(tok.Type, "type declaration")
|
||||
name := p.expect(tok.Identifier, "type name")
|
||||
m := ast.TypeDecl{
|
||||
Source: name.Source,
|
||||
Attributes: decos,
|
||||
Name: string(name.Runes),
|
||||
}
|
||||
if p.peekIs(0, tok.Lt) {
|
||||
m.TemplateParams = p.templateParams()
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (p *parser) attributes() ast.Attributes {
|
||||
var out ast.Attributes
|
||||
for p.match(tok.Attr) != nil && p.err == nil {
|
||||
name := p.expect(tok.Identifier, "attribute name")
|
||||
values := []string{}
|
||||
if p.match(tok.Lparen) != nil {
|
||||
for p.err == nil {
|
||||
values = append(values, string(p.next().Runes))
|
||||
if p.match(tok.Comma) == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
p.expect(tok.Rparen, "attribute values")
|
||||
}
|
||||
out = append(out, ast.Attribute{
|
||||
Source: name.Source,
|
||||
Name: string(name.Runes),
|
||||
Values: values,
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (p *parser) builtinDecl(decos ast.Attributes) ast.IntrinsicDecl {
|
||||
p.expect(tok.Function, "function declaration")
|
||||
name := p.expect(tok.Identifier, "function name")
|
||||
f := ast.IntrinsicDecl{
|
||||
Source: name.Source,
|
||||
Kind: ast.Builtin,
|
||||
Attributes: decos,
|
||||
Name: string(name.Runes),
|
||||
}
|
||||
if p.peekIs(0, tok.Lt) {
|
||||
f.TemplateParams = p.templateParams()
|
||||
}
|
||||
f.Parameters = p.parameters()
|
||||
if p.match(tok.Arrow) != nil {
|
||||
ret := p.templatedName()
|
||||
f.ReturnType = &ret
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (p *parser) operatorDecl(decos ast.Attributes) ast.IntrinsicDecl {
|
||||
p.expect(tok.Operator, "operator declaration")
|
||||
name := p.next()
|
||||
f := ast.IntrinsicDecl{
|
||||
Source: name.Source,
|
||||
Kind: ast.Operator,
|
||||
Attributes: decos,
|
||||
Name: string(name.Runes),
|
||||
}
|
||||
if p.peekIs(0, tok.Lt) {
|
||||
f.TemplateParams = p.templateParams()
|
||||
}
|
||||
f.Parameters = p.parameters()
|
||||
if p.match(tok.Arrow) != nil {
|
||||
ret := p.templatedName()
|
||||
f.ReturnType = &ret
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (p *parser) constructorDecl(decos ast.Attributes) ast.IntrinsicDecl {
|
||||
p.expect(tok.Constructor, "constructor declaration")
|
||||
name := p.next()
|
||||
f := ast.IntrinsicDecl{
|
||||
Source: name.Source,
|
||||
Kind: ast.Constructor,
|
||||
Attributes: decos,
|
||||
Name: string(name.Runes),
|
||||
}
|
||||
if p.peekIs(0, tok.Lt) {
|
||||
f.TemplateParams = p.templateParams()
|
||||
}
|
||||
f.Parameters = p.parameters()
|
||||
if p.match(tok.Arrow) != nil {
|
||||
ret := p.templatedName()
|
||||
f.ReturnType = &ret
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (p *parser) converterDecl(decos ast.Attributes) ast.IntrinsicDecl {
|
||||
p.expect(tok.Converter, "converter declaration")
|
||||
name := p.next()
|
||||
f := ast.IntrinsicDecl{
|
||||
Source: name.Source,
|
||||
Kind: ast.Converter,
|
||||
Attributes: decos,
|
||||
Name: string(name.Runes),
|
||||
}
|
||||
if p.peekIs(0, tok.Lt) {
|
||||
f.TemplateParams = p.templateParams()
|
||||
}
|
||||
f.Parameters = p.parameters()
|
||||
if p.match(tok.Arrow) != nil {
|
||||
ret := p.templatedName()
|
||||
f.ReturnType = &ret
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (p *parser) parameters() ast.Parameters {
|
||||
l := ast.Parameters{}
|
||||
p.expect(tok.Lparen, "function parameter list")
|
||||
if p.match(tok.Rparen) == nil {
|
||||
for p.err == nil {
|
||||
l = append(l, p.parameter())
|
||||
if p.match(tok.Comma) == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
p.expect(tok.Rparen, "function parameter list")
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func (p *parser) parameter() ast.Parameter {
|
||||
attributes := p.attributes()
|
||||
if p.peekIs(1, tok.Colon) {
|
||||
// name type
|
||||
name := p.expect(tok.Identifier, "parameter name")
|
||||
p.expect(tok.Colon, "parameter type")
|
||||
return ast.Parameter{
|
||||
Source: name.Source,
|
||||
Name: string(name.Runes),
|
||||
Attributes: attributes,
|
||||
Type: p.templatedName(),
|
||||
}
|
||||
}
|
||||
// type
|
||||
ty := p.templatedName()
|
||||
return ast.Parameter{
|
||||
Source: ty.Source,
|
||||
Attributes: attributes,
|
||||
Type: ty,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) string() string {
|
||||
s := p.expect(tok.String, "string")
|
||||
return string(s.Runes)
|
||||
}
|
||||
|
||||
func (p *parser) templatedName() ast.TemplatedName {
|
||||
name := p.expect(tok.Identifier, "type name")
|
||||
m := ast.TemplatedName{Source: name.Source, Name: string(name.Runes)}
|
||||
if p.match(tok.Lt) != nil {
|
||||
for p.err == nil {
|
||||
m.TemplateArgs = append(m.TemplateArgs, p.templatedName())
|
||||
if p.match(tok.Comma) == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
p.expect(tok.Gt, "template argument type list")
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (p *parser) templateParams() ast.TemplateParams {
|
||||
t := ast.TemplateParams{}
|
||||
p.expect(tok.Lt, "template parameter list")
|
||||
for p.err == nil && p.peekIs(0, tok.Identifier) {
|
||||
t = append(t, p.templateParam())
|
||||
}
|
||||
p.expect(tok.Gt, "template parameter list")
|
||||
return t
|
||||
}
|
||||
|
||||
func (p *parser) templateParam() ast.TemplateParam {
|
||||
name := p.match(tok.Identifier)
|
||||
t := ast.TemplateParam{
|
||||
Source: name.Source,
|
||||
Name: string(name.Runes),
|
||||
}
|
||||
if p.match(tok.Colon) != nil {
|
||||
t.Type = p.templatedName()
|
||||
}
|
||||
p.match(tok.Comma)
|
||||
return t
|
||||
}
|
||||
|
||||
func (p *parser) expect(kind tok.Kind, use string) tok.Token {
|
||||
if p.err != nil {
|
||||
return tok.Invalid
|
||||
}
|
||||
t := p.match(kind)
|
||||
if t == nil {
|
||||
if len(p.tokens) > 0 {
|
||||
p.err = fmt.Errorf("%v expected '%v' for %v, got '%v'",
|
||||
p.tokens[0].Source, kind, use, p.tokens[0].Kind)
|
||||
} else {
|
||||
p.err = fmt.Errorf("expected '%v' for %v, but reached end of file", kind, use)
|
||||
}
|
||||
return tok.Invalid
|
||||
}
|
||||
return *t
|
||||
}
|
||||
|
||||
func (p *parser) ident(use string) string {
|
||||
return string(p.expect(tok.Identifier, use).Runes)
|
||||
}
|
||||
|
||||
func (p *parser) match(kind tok.Kind) *tok.Token {
|
||||
if p.err != nil || len(p.tokens) == 0 {
|
||||
return nil
|
||||
}
|
||||
t := p.tokens[0]
|
||||
if t.Kind != kind {
|
||||
return nil
|
||||
}
|
||||
p.tokens = p.tokens[1:]
|
||||
return &t
|
||||
}
|
||||
|
||||
func (p *parser) next() *tok.Token {
|
||||
if p.err != nil {
|
||||
return nil
|
||||
}
|
||||
if len(p.tokens) == 0 {
|
||||
p.err = fmt.Errorf("reached end of file")
|
||||
}
|
||||
t := p.tokens[0]
|
||||
p.tokens = p.tokens[1:]
|
||||
return &t
|
||||
}
|
||||
|
||||
func (p *parser) peekIs(i int, kind tok.Kind) bool {
|
||||
t := p.peek(i)
|
||||
if t == nil {
|
||||
return false
|
||||
}
|
||||
return t.Kind == kind
|
||||
}
|
||||
|
||||
func (p *parser) peek(i int) *tok.Token {
|
||||
if len(p.tokens) <= i {
|
||||
return nil
|
||||
}
|
||||
return &p.tokens[i]
|
||||
}
|
||||
705
tools/src/tint/intrinsic/parser/parser_test.go
Normal file
705
tools/src/tint/intrinsic/parser/parser_test.go
Normal file
@@ -0,0 +1,705 @@
|
||||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package parser_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/ast"
|
||||
"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/parser"
|
||||
"dawn.googlesource.com/dawn/tools/src/utils"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
var ignoreSource = cmp.FilterPath(func(p cmp.Path) bool {
|
||||
return p.Last().String() == ".Source"
|
||||
}, cmp.Ignore())
|
||||
|
||||
func TestParser(t *testing.T) {
|
||||
type test struct {
|
||||
location string
|
||||
src string
|
||||
expect ast.AST
|
||||
}
|
||||
|
||||
for _, test := range []test{
|
||||
{
|
||||
utils.ThisLine(),
|
||||
"enum E {}",
|
||||
ast.AST{
|
||||
Enums: []ast.EnumDecl{{Name: "E"}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"enum E { A @attr B C }",
|
||||
ast.AST{
|
||||
Enums: []ast.EnumDecl{{
|
||||
Name: "E",
|
||||
Entries: []ast.EnumEntry{
|
||||
{Name: "A"},
|
||||
{
|
||||
Attributes: ast.Attributes{{
|
||||
Name: "attr",
|
||||
Values: []string{},
|
||||
}},
|
||||
Name: "B",
|
||||
},
|
||||
{Name: "C"},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"type T",
|
||||
ast.AST{
|
||||
Types: []ast.TypeDecl{{Name: "T"}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"type T<A, B, C>",
|
||||
ast.AST{
|
||||
Types: []ast.TypeDecl{{
|
||||
Name: "T",
|
||||
TemplateParams: ast.TemplateParams{
|
||||
{Name: "A"},
|
||||
{Name: "B"},
|
||||
{Name: "C"},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"@attr type T",
|
||||
ast.AST{
|
||||
Types: []ast.TypeDecl{{
|
||||
Attributes: ast.Attributes{
|
||||
{Name: "attr", Values: []string{}},
|
||||
},
|
||||
Name: "T",
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"@attr_a @attr_b type T",
|
||||
ast.AST{
|
||||
Types: []ast.TypeDecl{{
|
||||
Attributes: ast.Attributes{
|
||||
{Name: "attr_a", Values: []string{}},
|
||||
{Name: "attr_b", Values: []string{}},
|
||||
},
|
||||
Name: "T",
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
`@attr("a", "b") type T`, ast.AST{
|
||||
Types: []ast.TypeDecl{{
|
||||
Attributes: ast.Attributes{
|
||||
{Name: "attr", Values: []string{"a", "b"}},
|
||||
},
|
||||
Name: "T",
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
`@attr(1, "x") type T`, ast.AST{
|
||||
Types: []ast.TypeDecl{{
|
||||
Attributes: ast.Attributes{
|
||||
{Name: "attr", Values: []string{"1", "x"}},
|
||||
},
|
||||
Name: "T",
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"match M : A",
|
||||
ast.AST{
|
||||
Matchers: []ast.MatcherDecl{{
|
||||
Name: "M",
|
||||
Options: ast.MatcherOptions{
|
||||
ast.TemplatedName{Name: "A"},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"match M : A | B",
|
||||
ast.AST{
|
||||
Matchers: []ast.MatcherDecl{{
|
||||
Name: "M",
|
||||
Options: ast.MatcherOptions{
|
||||
ast.TemplatedName{Name: "A"},
|
||||
ast.TemplatedName{Name: "B"},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"fn F()",
|
||||
ast.AST{
|
||||
Builtins: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Builtin,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"@attr fn F()",
|
||||
ast.AST{
|
||||
Builtins: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Builtin,
|
||||
Name: "F",
|
||||
Attributes: ast.Attributes{
|
||||
{Name: "attr", Values: []string{}},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"fn F(a)",
|
||||
ast.AST{
|
||||
Builtins: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Builtin,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Type: ast.TemplatedName{Name: "a"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"fn F(a: T)",
|
||||
ast.AST{
|
||||
Builtins: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Builtin,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Name: "a", Type: ast.TemplatedName{Name: "T"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"fn F(a, b)",
|
||||
ast.AST{
|
||||
Builtins: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Builtin,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Type: ast.TemplatedName{Name: "a"}},
|
||||
{Type: ast.TemplatedName{Name: "b"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"fn F<A : B<C> >()",
|
||||
ast.AST{
|
||||
Builtins: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Builtin,
|
||||
Name: "F",
|
||||
TemplateParams: ast.TemplateParams{
|
||||
{
|
||||
Name: "A", Type: ast.TemplatedName{
|
||||
Name: "B",
|
||||
TemplateArgs: ast.TemplatedNames{
|
||||
{Name: "C"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"fn F<T>(a: X, b: Y<T>)",
|
||||
ast.AST{
|
||||
Builtins: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Builtin,
|
||||
Name: "F",
|
||||
TemplateParams: ast.TemplateParams{
|
||||
{Name: "T"},
|
||||
},
|
||||
Parameters: ast.Parameters{
|
||||
{Name: "a", Type: ast.TemplatedName{Name: "X"}},
|
||||
{Name: "b", Type: ast.TemplatedName{
|
||||
Name: "Y",
|
||||
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||
}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"fn F() -> X",
|
||||
ast.AST{
|
||||
Builtins: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Builtin,
|
||||
Name: "F",
|
||||
ReturnType: &ast.TemplatedName{Name: "X"},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"fn F() -> X<T>",
|
||||
ast.AST{
|
||||
Builtins: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Builtin,
|
||||
Name: "F",
|
||||
ReturnType: &ast.TemplatedName{
|
||||
Name: "X",
|
||||
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"op F()",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"@attr op F()",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
Attributes: ast.Attributes{
|
||||
{Name: "attr", Values: []string{}},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"op F(a)",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Type: ast.TemplatedName{Name: "a"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"op F(@blah a)",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{
|
||||
Attributes: ast.Attributes{{Name: "blah", Values: []string{}}},
|
||||
Type: ast.TemplatedName{Name: "a"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"op F(a: T)",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Name: "a", Type: ast.TemplatedName{Name: "T"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"op F(a, b)",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Type: ast.TemplatedName{Name: "a"}},
|
||||
{Type: ast.TemplatedName{Name: "b"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"op F<A : B<C> >()",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
TemplateParams: ast.TemplateParams{
|
||||
{
|
||||
Name: "A", Type: ast.TemplatedName{
|
||||
Name: "B",
|
||||
TemplateArgs: ast.TemplatedNames{
|
||||
{Name: "C"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"op F<T>(a: X, b: Y<T>)",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
TemplateParams: ast.TemplateParams{
|
||||
{Name: "T"},
|
||||
},
|
||||
Parameters: ast.Parameters{
|
||||
{Name: "a", Type: ast.TemplatedName{Name: "X"}},
|
||||
{Name: "b", Type: ast.TemplatedName{
|
||||
Name: "Y",
|
||||
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||
}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"op F() -> X",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
ReturnType: &ast.TemplatedName{Name: "X"},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"op F() -> X<T>",
|
||||
ast.AST{
|
||||
Operators: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Operator,
|
||||
Name: "F",
|
||||
ReturnType: &ast.TemplatedName{
|
||||
Name: "X",
|
||||
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"ctor F()",
|
||||
ast.AST{
|
||||
Constructors: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Constructor,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"@attr ctor F()",
|
||||
ast.AST{
|
||||
Constructors: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Constructor,
|
||||
Name: "F",
|
||||
Attributes: ast.Attributes{
|
||||
{Name: "attr", Values: []string{}},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"ctor F(a)",
|
||||
ast.AST{
|
||||
Constructors: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Constructor,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Type: ast.TemplatedName{Name: "a"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"ctor F(a: T)",
|
||||
ast.AST{
|
||||
Constructors: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Constructor,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Name: "a", Type: ast.TemplatedName{Name: "T"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"ctor F(a, b)",
|
||||
ast.AST{
|
||||
Constructors: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Constructor,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Type: ast.TemplatedName{Name: "a"}},
|
||||
{Type: ast.TemplatedName{Name: "b"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"ctor F<A : B<C> >()",
|
||||
ast.AST{
|
||||
Constructors: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Constructor,
|
||||
Name: "F",
|
||||
TemplateParams: ast.TemplateParams{
|
||||
{
|
||||
Name: "A", Type: ast.TemplatedName{
|
||||
Name: "B",
|
||||
TemplateArgs: ast.TemplatedNames{
|
||||
{Name: "C"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"ctor F<T>(a: X, b: Y<T>)",
|
||||
ast.AST{
|
||||
Constructors: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Constructor,
|
||||
Name: "F",
|
||||
TemplateParams: ast.TemplateParams{
|
||||
{Name: "T"},
|
||||
},
|
||||
Parameters: ast.Parameters{
|
||||
{Name: "a", Type: ast.TemplatedName{Name: "X"}},
|
||||
{Name: "b", Type: ast.TemplatedName{
|
||||
Name: "Y",
|
||||
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||
}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"ctor F() -> X",
|
||||
ast.AST{
|
||||
Constructors: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Constructor,
|
||||
Name: "F",
|
||||
ReturnType: &ast.TemplatedName{Name: "X"},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"ctor F() -> X<T>",
|
||||
ast.AST{
|
||||
Constructors: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Constructor,
|
||||
Name: "F",
|
||||
ReturnType: &ast.TemplatedName{
|
||||
Name: "X",
|
||||
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"conv F()",
|
||||
ast.AST{
|
||||
Converters: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Converter,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"@attr conv F()",
|
||||
ast.AST{
|
||||
Converters: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Converter,
|
||||
Name: "F",
|
||||
Attributes: ast.Attributes{
|
||||
{Name: "attr", Values: []string{}},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"conv F(a)",
|
||||
ast.AST{
|
||||
Converters: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Converter,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Type: ast.TemplatedName{Name: "a"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"conv F(a: T)",
|
||||
ast.AST{
|
||||
Converters: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Converter,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Name: "a", Type: ast.TemplatedName{Name: "T"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"conv F(a, b)",
|
||||
ast.AST{
|
||||
Converters: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Converter,
|
||||
Name: "F",
|
||||
Parameters: ast.Parameters{
|
||||
{Type: ast.TemplatedName{Name: "a"}},
|
||||
{Type: ast.TemplatedName{Name: "b"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"conv F<A : B<C> >()",
|
||||
ast.AST{
|
||||
Converters: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Converter,
|
||||
Name: "F",
|
||||
TemplateParams: ast.TemplateParams{
|
||||
{
|
||||
Name: "A", Type: ast.TemplatedName{
|
||||
Name: "B",
|
||||
TemplateArgs: ast.TemplatedNames{
|
||||
{Name: "C"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"conv F<T>(a: X, b: Y<T>)",
|
||||
ast.AST{
|
||||
Converters: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Converter,
|
||||
Name: "F",
|
||||
TemplateParams: ast.TemplateParams{
|
||||
{Name: "T"},
|
||||
},
|
||||
Parameters: ast.Parameters{
|
||||
{Name: "a", Type: ast.TemplatedName{Name: "X"}},
|
||||
{Name: "b", Type: ast.TemplatedName{
|
||||
Name: "Y",
|
||||
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||
}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"conv F() -> X",
|
||||
ast.AST{
|
||||
Converters: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Converter,
|
||||
Name: "F",
|
||||
ReturnType: &ast.TemplatedName{Name: "X"},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
},
|
||||
}, { ///////////////////////////////////////////////////////////////////
|
||||
utils.ThisLine(),
|
||||
"conv F() -> X<T>",
|
||||
ast.AST{
|
||||
Converters: []ast.IntrinsicDecl{{
|
||||
Kind: ast.Converter,
|
||||
Name: "F",
|
||||
ReturnType: &ast.TemplatedName{
|
||||
Name: "X",
|
||||
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||
},
|
||||
Parameters: ast.Parameters{},
|
||||
}},
|
||||
}},
|
||||
} {
|
||||
got, err := parser.Parse(test.src, "file.txt")
|
||||
if err != nil {
|
||||
t.Errorf("\n%v\nWhile parsing:\n%s\nParse() returned error: %v",
|
||||
test.location, test.src, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, &test.expect, ignoreSource); diff != "" {
|
||||
t.Errorf("\n%v\nWhile parsing:\n%s\n\n%s",
|
||||
test.location, test.src, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
type test struct {
|
||||
src string
|
||||
expect string
|
||||
}
|
||||
|
||||
for _, test := range []test{
|
||||
{
|
||||
"£",
|
||||
"test.txt:1:1: unexpected '£'",
|
||||
},
|
||||
{
|
||||
"123",
|
||||
"test.txt:1:1 unexpected token 'integer'",
|
||||
},
|
||||
{
|
||||
"@123",
|
||||
"test.txt:1:2 expected 'ident' for attribute name, got 'integer'",
|
||||
},
|
||||
} {
|
||||
got, err := parser.Parse(test.src, "test.txt")
|
||||
gotErr := ""
|
||||
if err != nil {
|
||||
gotErr = err.Error()
|
||||
}
|
||||
if test.expect != gotErr {
|
||||
t.Errorf(`Parse() returned error "%+v", expected error "%+v"`, gotErr, test.expect)
|
||||
}
|
||||
if got != nil {
|
||||
t.Errorf("Lex() returned non-nil for error")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user