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 }