pulumi/pkg/compiler/parser.go
joeduffy 2665a1a4c4 Check dependencies for validity
This change introduces a check during parse-tree analysis that dependencies
are valid, along with some tests.  Note that this could technically happen later
during semantic analysis and I will likely move it so that we can get better
diagnostics (more errors before failing).  I've also cleaned up and unified some
of the logic by introducing the general notion of a Visitor interface, which the
parse tree analyzer, binder, and analyzers to come will all implement.
2016-11-16 11:09:45 -08:00

59 lines
1.6 KiB
Go

// Copyright 2016 Marapongo, Inc. All rights reserved.
package compiler
import (
"github.com/golang/glog"
"github.com/marapongo/mu/pkg/ast"
"github.com/marapongo/mu/pkg/diag"
"github.com/marapongo/mu/pkg/encoding"
"github.com/marapongo/mu/pkg/errors"
)
// Parse transforms a program's input text into a parse tree.
type Parser interface {
Phase
// Parse detects and parses input from the given path. If an error occurs, the return value will be nil. It is
// expected that errors are conveyed using the diag.Sink interface.
Parse(doc *diag.Document) *ast.Stack
}
func NewParser(c Compiler) Parser {
return &parser{c}
}
type parser struct {
c Compiler
}
func (p *parser) Diag() diag.Sink {
return p.c.Diag()
}
func (p *parser) Parse(doc *diag.Document) *ast.Stack {
glog.Infof("Parsing Mufile: %v (len(body)=%v)", doc.File, len(doc.Body))
if glog.V(2) {
defer func() {
glog.V(2).Infof("Parsing Mufile '%v' completed w/ %v warnings and %v errors",
doc.File, p.Diag().Warnings(), p.Diag().Errors())
}()
}
// We support many file formats. Detect the file extension and deserialize the contents.
// TODO: we need to expand templates as part of the parsing process
var stack ast.Stack
marshaler, has := encoding.Marshalers[doc.Ext()]
if !has {
glog.Fatalf("No marshaler registered for this Mufile extension: %v", doc.Ext())
return nil
}
if err := marshaler.Unmarshal(doc.Body, &stack); err != nil {
p.Diag().Errorf(errors.IllegalMufileSyntax.WithDocument(doc), err)
// TODO: it would be great if we issued an error per issue found in the file with line/col numbers.
return nil
}
return &stack
}