github.com/openconfig/goyang@v1.4.5/pkg/yang/ast.go (about)

     1  // Copyright 2015 Google Inc.
     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  
    15  package yang
    16  
    17  // This file implements BuildAST() and its associated helper structs and
    18  // functions for constructing an AST of Nodes from a Statement tree. This
    19  // function also populates all typedefs into a type cache.
    20  //
    21  // The initTypes function generates the helper struct and functions that
    22  // recursively fill in the various Node structures defined in yang.go.
    23  // BuildAST() then uses those functions to convert raw parsed Statements into
    24  // an AST.
    25  
    26  import (
    27  	"errors"
    28  	"fmt"
    29  	"reflect"
    30  	"strings"
    31  )
    32  
    33  func init() {
    34  	// Initialize the global variables `typeMap` and `nameMap`.
    35  	// By doing this, we are making the assumption that all modules will be
    36  	// parsed according to the type hierarchy rooted at `meta`, and thus
    37  	// all input YANG modules will be parsed in this manner.
    38  	initTypes(reflect.TypeOf(&meta{}))
    39  }
    40  
    41  // A yangStatement contains all information needed to build a particular
    42  // type of statement into an AST node.
    43  type yangStatement struct {
    44  	// funcs is the map of YANG field names to the function that populates
    45  	// the statement into the AST node.
    46  	funcs map[string]func(*Statement, reflect.Value, reflect.Value, *typeDictionary) error
    47  	// required is a list of fields that must be present in the statement.
    48  	required []string
    49  	// sRequired maps a statement name to a list of required sub-field
    50  	// names. The statement name can be an alias of the primary field type.
    51  	//    e.g. If a field is required by statement type foo, then only foo
    52  	//    should have the field. If bar is an alias of foo, it must not
    53  	//    have this field.
    54  	sRequired map[string][]string
    55  	// addext is the function to handle possible extensions.
    56  	addext func(*Statement, reflect.Value, reflect.Value) error
    57  }
    58  
    59  // newYangStatement creates a new yangStatement.
    60  func newYangStatement() *yangStatement {
    61  	return &yangStatement{
    62  		funcs:     make(map[string]func(*Statement, reflect.Value, reflect.Value, *typeDictionary) error),
    63  		sRequired: make(map[string][]string),
    64  	}
    65  }
    66  
    67  var (
    68  	// The following maps are built up at init time.
    69  	// typeMap provides a lookup from a Node type to the corresponding
    70  	// yangStatement.
    71  	typeMap = map[reflect.Type]*yangStatement{}
    72  	// nameMap provides a lookup from a keyword string to the corresponding
    73  	// concrete type implementing the Node interface (see yang.go).
    74  	nameMap = map[string]reflect.Type{}
    75  
    76  	// The following are helper types used by the implementation.
    77  	statementType = reflect.TypeOf(&Statement{})
    78  	nilValue      = reflect.ValueOf(nil)
    79  	// nodeType is the reflect.Type of the Node interface.
    80  	nodeType = reflect.TypeOf((*Node)(nil)).Elem()
    81  )
    82  
    83  // meta is a collection of top-level statements.  There is no actual
    84  // statement named "meta".  All other statements are a sub-statement of one
    85  // of the meta statements.
    86  type meta struct {
    87  	Module []*Module `yang:"module"`
    88  }
    89  
    90  // aliases is a map of "aliased" names, that is, two types of statements
    91  // that parse (nearly) the same.
    92  // NOTE: This only works for root-level aliasing for now, which is good enough
    93  // for module/submodule. This is because yangStatement.funcs doesn't store the
    94  // handler function for aliased fields, and sRequired also may only store the
    95  // correct values when processing a root-level statement due to aliasing. These
    96  // issues would need to be fixed in order to support aliasing for non-top-level
    97  // statements.
    98  var aliases = map[string]string{
    99  	"submodule": "module",
   100  }
   101  
   102  // buildASTWithTypeDict creates an AST for the input statement, and returns its
   103  // root node. It also takes as input a type dictionary into which any
   104  // encountered typedefs within the statement are cached.
   105  func buildASTWithTypeDict(stmt *Statement, types *typeDictionary) (Node, error) {
   106  	v, err := build(stmt, nilValue, types)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	return v.Interface().(Node), nil
   111  }
   112  
   113  // build builds and returns an AST from the statement stmt and with parent node
   114  // parent. It also takes as input a type dictionary types into which any
   115  // encountered typedefs within the statement are cached. The type of value
   116  // returned depends on the keyword in stmt (see yang.go). It returns an error
   117  // if it cannot build the statement into its corresponding Node type.
   118  func build(stmt *Statement, parent reflect.Value, types *typeDictionary) (v reflect.Value, err error) {
   119  	defer func() {
   120  		// If we are returning a real Node then call addTypedefs
   121  		// if the node possibly contains typedefs.
   122  		// Cache these in the typedef cache for look-ups.
   123  		if err != nil || v == nilValue {
   124  			return
   125  		}
   126  		if t, ok := v.Interface().(Typedefer); ok {
   127  			types.addTypedefs(t)
   128  		}
   129  	}()
   130  	keyword := stmt.Keyword
   131  	if k, ok := aliases[stmt.Keyword]; ok {
   132  		keyword = k
   133  	}
   134  	t := nameMap[keyword]
   135  	y := typeMap[t]
   136  	// Keep track of which substatements are present in the statement.
   137  	found := map[string]bool{}
   138  
   139  	// Get the struct type we are pointing to.
   140  	t = t.Elem()
   141  	// v is a pointer to the instantiated structure we are building.
   142  	v = reflect.New(t)
   143  
   144  	// Handle special cases that are not actually substatements:
   145  
   146  	if fn := y.funcs["Name"]; fn != nil {
   147  		// Name uses stmt directly.
   148  		if err := fn(stmt, v, parent, types); err != nil {
   149  			return nilValue, err
   150  		}
   151  	}
   152  	if fn := y.funcs["Statement"]; fn != nil {
   153  		// Statement uses stmt directly.
   154  		if err := fn(stmt, v, parent, types); err != nil {
   155  			return nilValue, err
   156  		}
   157  	}
   158  	if fn := y.funcs["Parent"]; fn != nil {
   159  		// parent is the parent node, which is nilValue (reflect.ValueOf(nil)) if there is none.
   160  		// parent.IsValid will return false when parent is a nil interface
   161  		// parent.IsValid will true if parent references a concrete type
   162  		// (even if it is nil).
   163  		if parent.IsValid() {
   164  			if err := fn(stmt, v, parent, types); err != nil {
   165  				return nilValue, err
   166  			}
   167  		}
   168  	}
   169  
   170  	// Now handle the substatements
   171  
   172  	for _, ss := range stmt.statements {
   173  		found[ss.Keyword] = true
   174  		fn := y.funcs[ss.Keyword]
   175  		switch {
   176  		case fn != nil:
   177  			// Normal case, the keyword is known.
   178  			if err := fn(ss, v, parent, types); err != nil {
   179  				return nilValue, err
   180  			}
   181  		case len(strings.Split(ss.Keyword, ":")) == 2:
   182  			// Keyword is not known but it has a prefix so it might
   183  			// be an extension.
   184  			if y.addext == nil {
   185  				return nilValue, fmt.Errorf("%s: no extension function", ss.Location())
   186  			}
   187  			y.addext(ss, v, parent)
   188  		default:
   189  			return nilValue, fmt.Errorf("%s: unknown %s field: %s", ss.Location(), stmt.Keyword, ss.Keyword)
   190  		}
   191  	}
   192  
   193  	// Make sure all of our required field are there.
   194  	for _, r := range y.required {
   195  		if !found[r] {
   196  			return nilValue, fmt.Errorf("%s: missing required %s field: %s", stmt.Location(), stmt.Keyword, r)
   197  		}
   198  	}
   199  
   200  	// Make sure required fields based on our keyword are there (module vs submodule)
   201  	for _, r := range y.sRequired[stmt.Keyword] {
   202  		if !found[r] {
   203  			return nilValue, fmt.Errorf("%s: missing required %s field: %s", stmt.Location(), stmt.Keyword, r)
   204  		}
   205  	}
   206  
   207  	// Make sure we don't have any field set that is required by a different keyword.
   208  	for n, or := range y.sRequired {
   209  		if n == stmt.Keyword {
   210  			continue
   211  		}
   212  		for _, r := range or {
   213  			if found[r] {
   214  				return nilValue, fmt.Errorf("%s: unknown %s field: %s", stmt.Location(), stmt.Keyword, r)
   215  			}
   216  		}
   217  	}
   218  	return v, nil
   219  }
   220  
   221  // initTypes creates the functions necessary to build a Statement into the
   222  // given the type "at" based on its possible substatements. at must implement
   223  // Node, with its concrete type being a pointer to a struct defined in yang.go.
   224  //
   225  // This function also builds up the functions to populate the input type
   226  // dictionary types with any encountered typedefs within the statement.
   227  //
   228  // For each field of the struct with a yang tag (e.g., `yang:"command"`), a
   229  // function is created with "command" as its unique ID.  The complete map of
   230  // builder functions for at is then added to the typeMap map with at as the
   231  // key. The idea is to call these builder functions for each substatement
   232  // encountered.
   233  //
   234  // The functions have the form:
   235  //
   236  //	func fn(ss *Statement, v, p reflect.Value, types *typeDictionary) error
   237  //
   238  // Given stmt as a Statement of type at, ss is a substatement of stmt (in a few
   239  // exceptional cases, ss is the Statement itself).  v must have the same type
   240  // as at and is the structure being filled in.  p is the parent Node, or nil.
   241  // types is the type dictionary cache of the current set of modules being parsed,
   242  // which is used for looking up typedefs.  p is only used to set the Parent
   243  // field of a Node.  For example, given the following structure and variables:
   244  //
   245  //	type Include struct {
   246  //		Name         string       `yang:"Name"`
   247  //		Source       *Statement   `yang:"Statement"`
   248  //		Parent       Node         `yang:"Parent"`
   249  //		Extensions   []*Statement `yang:"Ext"`
   250  //		RevisionDate *Value       `yang:"revision-date"`
   251  //	}
   252  //
   253  //	var inc = &Include{}
   254  //	var vInc = reflect.ValueOf(inc)
   255  //	var tInc = reflect.TypeOf(inc)
   256  //
   257  // Functions are created for each fields and named Name, Statement, Parent, Ext,
   258  // and revision-date.
   259  //
   260  // The function built for RevisionDate will be called for any substatement,
   261  // ds, of stmt that has the keyword "revision-date" along with the value of
   262  // vInc and its parent:
   263  //
   264  //	typeMap[tInc]["revision-date"](ss, vInc, parent, types)
   265  //
   266  // Normal fields are all processed this same way.
   267  //
   268  // The other 4 fields are special.  In the case of Name, Statement, and Parent,
   269  // the function is passed stmt, rather than ss, as these fields are not filled in
   270  // by substatements.
   271  //
   272  // The Name command must set its field to the Statement's argument.  The
   273  // Statement command must set its field to the Statement itself.  The
   274  // Parent command must set its field with the Node of its parent (the
   275  // parent parameter).
   276  //
   277  // The Ext command is unique and must decode into a []*Statement.  This is a
   278  // slice of all statements that use unknown keywords with a prefix (in a valid
   279  // .yang file these should be the extensions).
   280  //
   281  // The Field can have attributes delimited by a ','.  The only
   282  // supported attributes are:
   283  //
   284  //	nomerge:       Do not merge this field
   285  //	required:      This field must be populated
   286  //	required=KIND: This field must be populated if the keyword is KIND
   287  //	               otherwise this field must not be present.
   288  //	               (This is to support merging Module and SubModule).
   289  //
   290  // If at contains substructures, initTypes recurses on the substructures.
   291  func initTypes(at reflect.Type) {
   292  	if at.Kind() != reflect.Ptr || at.Elem().Kind() != reflect.Struct {
   293  		panic(fmt.Sprintf("interface not a struct pointer, is %v", at))
   294  	}
   295  	if typeMap[at] != nil {
   296  		return // we already defined this type
   297  	}
   298  
   299  	y := newYangStatement()
   300  	typeMap[at] = y
   301  	t := at.Elem()
   302  	for i := 0; i != t.NumField(); i++ {
   303  		i := i
   304  		f := t.Field(i)
   305  		yang := f.Tag.Get("yang")
   306  		if yang == "" {
   307  			continue
   308  		}
   309  		parts := strings.Split(yang, ",")
   310  		name := parts[0]
   311  		if a, ok := aliases[name]; ok {
   312  			name = a
   313  		}
   314  
   315  		const reqe = "required="
   316  		for _, p := range parts[1:] {
   317  			switch {
   318  			case p == "nomerge":
   319  			case p == "required":
   320  				y.required = append(y.required, name)
   321  			case strings.HasPrefix(p, reqe):
   322  				p = p[len(reqe):]
   323  				y.sRequired[p] = append(y.sRequired[p], name)
   324  			default:
   325  				panic(f.Name + ": unknown tag: " + p)
   326  			}
   327  		}
   328  
   329  		// Ext means this is where we squirrel away extensions
   330  		if name == "Ext" {
   331  			// stmt is the extension to put into v at for field f.
   332  			y.addext = func(stmt *Statement, v, _ reflect.Value) error {
   333  				if v.Type() != at {
   334  					panic(fmt.Sprintf("given type %s, need type %s", v.Type(), at))
   335  				}
   336  				fv := v.Elem().Field(i)
   337  				fv.Set(reflect.Append(fv, reflect.ValueOf(stmt)))
   338  				return nil
   339  			}
   340  			continue
   341  		}
   342  
   343  		// descend runs initType on dt if it has not already done so.
   344  		descend := func(name string, dt reflect.Type) {
   345  			switch nameMap[name] {
   346  			case nil:
   347  				nameMap[name] = dt
   348  				initTypes(dt) // Make sure that structure type is included
   349  			case dt:
   350  			default:
   351  				panic("redeclared type " + name)
   352  			}
   353  		}
   354  
   355  		// Create a function, fn, that will build the field from a
   356  		// Statement.  These functions are used when actually making
   357  		// an AST from a Statement Tree.
   358  		var fn func(*Statement, reflect.Value, reflect.Value, *typeDictionary) error
   359  
   360  		// The field can be a pointer, a slice or a string
   361  		switch f.Type.Kind() {
   362  		default:
   363  			panic(fmt.Sprintf("invalid type: %v", f.Type.Kind()))
   364  
   365  		case reflect.Interface:
   366  			// The only case of this should be the "Parent" field.
   367  			if name != "Parent" {
   368  				panic(fmt.Sprintf("interface field is %s, not Parent", name))
   369  			}
   370  			fn = func(stmt *Statement, v, p reflect.Value, types *typeDictionary) error {
   371  				if !p.Type().Implements(nodeType) {
   372  					panic(fmt.Sprintf("invalid interface: %v", f.Type.Kind()))
   373  				}
   374  				v.Elem().Field(i).Set(p)
   375  				return nil
   376  			}
   377  		case reflect.String:
   378  			// The only case of this should be the "Name" field
   379  			if name != "Name" {
   380  				panic(fmt.Sprintf("string field is %s, not Name", name))
   381  			}
   382  			fn = func(stmt *Statement, v, _ reflect.Value, types *typeDictionary) error {
   383  				if v.Type() != at {
   384  					panic(fmt.Sprintf("got type %v, want %v", v.Type(), at))
   385  				}
   386  				fv := v.Elem().Field(i)
   387  				if fv.String() != "" {
   388  					return errors.New(stmt.Keyword + ": already set")
   389  				}
   390  
   391  				v.Elem().Field(i).SetString(stmt.Argument)
   392  				return nil
   393  			}
   394  
   395  		case reflect.Ptr:
   396  			if f.Type == statementType {
   397  				// The only case of this should be the
   398  				// "Statement" field
   399  				if name != "Statement" {
   400  					panic(fmt.Sprintf("string field is %s, not Statement", name))
   401  				}
   402  				fn = func(stmt *Statement, v, _ reflect.Value, types *typeDictionary) error {
   403  					if v.Type() != at {
   404  						panic(fmt.Sprintf("got type %v, want %v", v.Type(), at))
   405  					}
   406  					v.Elem().Field(i).Set(reflect.ValueOf(stmt))
   407  					return nil
   408  				}
   409  				break
   410  			}
   411  
   412  			// Make sure our field type is also setup.
   413  			descend(name, f.Type)
   414  
   415  			fn = func(stmt *Statement, v, p reflect.Value, types *typeDictionary) error {
   416  				if v.Type() != at {
   417  					panic(fmt.Sprintf("given type %s, need type %s", v.Type(), at))
   418  				}
   419  				fv := v.Elem().Field(i)
   420  				if !fv.IsNil() {
   421  					return errors.New(stmt.Keyword + ": already set")
   422  				}
   423  
   424  				// Use build to build the value for this field.
   425  				sv, err := build(stmt, v, types)
   426  				if err != nil {
   427  					return err
   428  				}
   429  				v.Elem().Field(i).Set(sv)
   430  				return nil
   431  			}
   432  
   433  		case reflect.Slice:
   434  			// A slice at this point is always a slice of
   435  			// substructures.  We may see the same keyword multiple
   436  			// times, each time we see it we just append to the
   437  			// slice.
   438  			st := f.Type.Elem()
   439  			switch st.Kind() {
   440  			default:
   441  				panic(fmt.Sprintf("invalid type: %v", st.Kind()))
   442  			case reflect.Ptr:
   443  				descend(name, st)
   444  				fn = func(stmt *Statement, v, p reflect.Value, types *typeDictionary) error {
   445  					if v.Type() != at {
   446  						panic(fmt.Sprintf("given type %s, need type %s", v.Type(), at))
   447  					}
   448  					sv, err := build(stmt, v, types)
   449  					if err != nil {
   450  						return err
   451  					}
   452  
   453  					fv := v.Elem().Field(i)
   454  					fv.Set(reflect.Append(fv, sv))
   455  					return nil
   456  				}
   457  			}
   458  		}
   459  		y.funcs[name] = fn
   460  	}
   461  }