// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// A library for EBNF grammars. The input is text ([]byte) satisfying
// the following grammar (represented itself in EBNF):
//
//	Production  = name "=" Expression "." .
//	Expression  = Alternative { "|" Alternative } .
//	Alternative = Term { Term } .
//	Term        = name | token [ "..." token ] | Group | Option | Repetition .
//	Group       = "(" Expression ")" .
//	Option      = "[" Expression "]" .
//	Repetition  = "{" Expression "}" .
//
// A name is a Go identifier, a token is a Go string, and comments
// and white space follow the same rules as for the Go language.
// Production names starting with an uppercase Unicode letter denote
// non-terminal productions (i.e., productions which allow white-space
// and comments between tokens); all other production names denote
// lexical productions.
//
package ebnf

import (
	"container/vector";
	"go/scanner";
	"go/token";
	"os";
	"unicode";
	"utf8";
)


// ----------------------------------------------------------------------------
// Internal representation

type (
	// An Expression node represents a production expression.
	Expression interface {
		// Pos is the position of the first character of the syntactic construct
		Pos() token.Position;
	};

	// An Alternative node represents a non-empty list of alternative expressions.
	Alternative []Expression;  // x | y | z

	// A Sequence node represents a non-empty list of sequential expressions.
	Sequence []Expression;  // x y z

	// A Name node represents a production name.
	Name struct {
		token.Position;
		String string;
	};

	// A Token node represents a literal.
	Token struct {
		token.Position;
		String string;
	};

	// A List node represents a range of characters.
	Range struct {
		Begin, End *Token;  // begin ... end
	};

	// A Group node represents a grouped expression.
	Group struct {
		token.Position;
		Body Expression;  // (body)
	};

	// An Option node represents an optional expression.
	Option struct {
		token.Position;
		Body Expression;  // [body]
	};

	// A Repetition node represents a repeated expression.
	Repetition struct {
		token.Position;
		Body Expression;  // {body}
	};

	// A Production node represents an EBNF production.
	Production struct {
		Name *Name;
		Expr Expression;
	};

	// A Grammar is a set of EBNF productions. The map
	// is indexed by production name.
	//
	Grammar map [string] *Production;
)


func (x Alternative) Pos() token.Position {
	return x[0].Pos();  // the parser always generates non-empty Alternative
}


func (x Sequence) Pos() token.Position {
	return x[0].Pos();  // the parser always generates non-empty Sequences
}


func (x Range) Pos() token.Position {
	return x.Begin.Pos();
}


func (p *Production) Pos() token.Position {
	return p.Name.Pos();
}


// ----------------------------------------------------------------------------
// Grammar verification

func isLexical(name string) bool {
	ch, _ := utf8.DecodeRuneInString(name);
	return !unicode.IsUpper(ch);
}


type verifier struct {
	scanner.ErrorVector;
	worklist vector.Vector;
	reached Grammar;  // set of productions reached from (and including) the root production
	grammar Grammar;
}


func (v *verifier) push(prod *Production) {
	name := prod.Name.String;
	if _, found := v.reached[name]; !found {
		v.worklist.Push(prod);
		v.reached[name] = prod;
	}
}


func (v *verifier) verifyChar(x *Token) int {
	s := x.String;
	if utf8.RuneCountInString(s) != 1 {
		v.Error(x.Pos(), "single char expected, found " + s);
		return 0;
	}
	ch, _ := utf8.DecodeRuneInString(s);
	return ch;
}


func (v *verifier) verifyExpr(expr Expression, lexical bool) {
	switch x := expr.(type) {
	case nil:
		// empty expression
	case Alternative:
		for _, e := range x {
			v.verifyExpr(e, lexical);
		}
	case Sequence:
		for _, e := range x {
			v.verifyExpr(e, lexical);
		}
	case *Name:
		// a production with this name must exist;
		// add it to the worklist if not yet processed
		if prod, found := v.grammar[x.String]; found {
			v.push(prod);
		} else {
			v.Error(x.Pos(), "missing production " + x.String);
		}
		// within a lexical production references
		// to non-lexical productions are invalid
		if lexical && !isLexical(x.String) {
			v.Error(x.Pos(), "reference to non-lexical production " + x.String);
		}
	case *Token:
		// nothing to do for now
	case *Range:
		i := v.verifyChar(x.Begin);
		j := v.verifyChar(x.End);
		if i >= j {
			v.Error(x.Pos(), "decreasing character range");
		}
	case *Group:
		v.verifyExpr(x.Body, lexical);
	case *Option:
		v.verifyExpr(x.Body, lexical);
	case *Repetition:
		v.verifyExpr(x.Body, lexical);
	default:
		panic("unreachable");
	}
}


func (v *verifier) verify(grammar Grammar, start string) {
	// find root production
	root, found := grammar[start];
	if !found {
		var noPos token.Position;
		v.Error(noPos, "no start production " + start);
		return;
	}

	// initialize verifier
	v.ErrorVector.Init();
	v.worklist.Init(0);
	v.reached = make(Grammar);
	v.grammar = grammar;

	// work through the worklist
	v.push(root);
	for v.worklist.Len() > 0 {
		prod := v.worklist.Pop().(*Production);
		v.verifyExpr(prod.Expr, isLexical(prod.Name.String));
	}

	// check if all productions were reached
	if len(v.reached) < len(v.grammar) {
		for name, prod := range v.grammar {
			if _, found := v.reached[name]; !found {
				v.Error(prod.Pos(), name + " is unreachable");
			}
		}
	}
}


// Verify checks that:
//	- all productions used are defined
//	- all productions defined are used when beginning at start
//	- lexical productions refer only to other lexical productions
//
func Verify(grammar Grammar, start string) os.Error {
	var v verifier;
	v.verify(grammar, start);
	return v.GetError(scanner.Sorted);
}
