package parser

import (
	"fmt"
	"math"
	"mojom/mojom_parser/lexer"
	"mojom/mojom_parser/mojom"
	"strconv"
)

// The code in this file implements  recursive-descent, predictive parsing
// for the context-free grammar listed below.
//
// The grammar is similar to the grammar in the document "Mojom Language
// Specification", but it has been modified in order to make it LL(1). This
// is necessary in order to be able to use it to do predictive top-down
// parsing. (See Section 4.4.3 of "Compilers: Principles, Techniques and Tools"
// 2nd Edition, by Aho et al."). This requirement explains the slight awkwardness
// seen below regarding the handling of Mojom attributes. (Disclaimer: There are
// a few productions that technically render the grammar LL(n) for some small
// integer n rather than strictly LL(1). But this does not affect the parsing
// in any significant way.)
//
// Our recursive descent logic is implemented in the methods below with names of
// the form "parseX()" where "X" is (an altered spelling of) one of our
// non-terminal symbols. Each of the productions below has been copied to the
// piece of code responsible for implementing the logic associated with the
// production.
//
// Key:
// Upper case means non-terminals.
// Lower case means terminals and refers to the TokenKind enum in lexer/tokens.go.
// Vertical bar | means alternatives.
// Braces {} means zero or more.
// Brackets [] means zero or one.
//
// ATTR_MOJOM_FILE      -> [ATTRIBUTES] MOJOM_FILE
// MOJOM_FILE           -> MODULE_DECL {IMPORT_STMNT} {ATTR_MOJOM_DECL}
// MOJOM_FILE           -> IMPORT_STMNT {IMPORT_STMNT} {ATTR_MOJOM_DECL}
// MOJOM_FILE           -> MOJOM_DECL {ATTR_MOJOM_DECL}

// MODULE_DECL          -> module IDENTIFIER semi
// IMPORT_STMNT         -> import string_literal

// ATTR_MOJOM_DECL      -> [ATTRIBUTES] MOJOM_DECL
// MOJOM_DECL           -> INTRFC_DECL | STRUCT_DECL | UNION_DECL | ENUM_DECL | CONSTANT_DECL

// ATTRIBUTES           -> lbracket ATTR_ASSIGNMENT { comma, ATTR_ASSIGNMENT}
// ATTR_ASSIGNMENT      -> name equals name | name equals LITERAL_VALUE

// INTRFC_DECL          -> interface name lbrace INTRFC_BODY rbrace semi
// INTRFC_BODY          -> {ATTR_INTRFC_ELEMENT}
// ATTR_INTRFC_ELEMENT  -> [ATTRIBUTES] INTRFC_ELEMENT
// INTRFC_ELEMENT       -> METHOD_DECL | ENUM_DECL | CONSTANT_DECL

// METHOD_DECL          -> name [ordinal] lparen [PARAM_LIST] rparen [response lparen [PARAM_LIST] rparen] semi
// PARAM_LIST           -> PARAM_DECL {comma, PARAM_DECL}
// PARAM_DECL           -> [ATTRIBUTES] TYPE NAME [ordinal]

// STRUCT_DECL          -> struct name lbrace STRUCT_BODY rbrace semi
// STRUCT_BODY          -> {ATTR_STRUCT_ELEMENT}
// ATTR_STRUCT_ELEMENT  -> [ATTRIBUTES] STRUCT_ELEMENT
// STRUCT_ELEMENT       -> STRUCT_FIELD | ENUM_DECL | CONSTANT_DECL
// STRUCT_FIELD         -> TYPE name [ordinal] [equals DEFAULT_VALUE] semi
// DEFAULT_VALUE        -> COMPATIBLE_VALUE_REF | default
// COMPATIBLE_VALUE_REF -> VALUE_REF {{that resolves to a concrete value whose type is assignment compatible with the type of the assignee}}

// UNION_DECL           -> union name lbrace UNION_BODY rbrace semi
// UNION_BODY           -> {UNION_FIELD_DECL}
// UNION_FIELD_DECL     -> [ATTRIBUTES] TYPE name [ordinal] semi

// ENUM_DECL            -> enum name lbrace ENUM_BODY rbrace semi
// ENUM_BODY            -> [ ENUN_VALUE {, ENUM_VALUE} [,] ]
// ENUM_VALUE           -> [ATTRIBUTES] name [equals ENUM_VAL_INITIALIZER]
// ENUM_VAL_INITIALIZER -> INT32_VAL | APPROPRIATE_ENUM_VALUE_REF
// INT32_VAL            -> VALUE_REF {{that resolves to a concrete value of integer type that may be assigned to an int32.}}
// APPROPRIATE_ENUM_VALUE_REF
//                      -> USER_VALUE_REF {{that resolves to an enum value of the same enum type as the initializee
//                                          and which occurs earlier in declaration order than the initializee.}}

// CONSTANT_DECL        -> const CONST_OK_TYPE name equals COMPATIBLE_VALUE_REF semi
// CONST_OK_TYPE        -> SIMPLE_TYPE | string | ENUM_TYPE {{See https://github.com/domokit/mojo/issues/607}}

// VALUE_REF            -> USER_VALUE_REF | LITERAL_VALUE | BUILT_IN_FLOAT_CONST
// USER_VALUE_REF       -> IDENTIFIER {{that resolves to a user-defined constant or enum value}}
// BUILT_IN_FLOAT_CONST -> IDENTIFIER {{that does not resolve to a user-defined constant or enum value
//                         and that is equal to one of the following strings:
//                         "float.INFINITY", "float.NEGATIVE_INFINITY", "float.NAN",
//                         "double.INFINITY", "double.NEGATIVE_INFINITY","double.NAN"}
// LITERAL_VALUE        -> BOOL_LITERAL | string_literal | NUMBER_LITERAL
// BOOL_LITERAL         -> true | false
// NUMBER_LITERAL       -> [plus | minus] POS_NUM_LITERAL
// INTEGER_LITERAL      -> [plus | minus] POS_INT_LITERAL
// POS_NUM_LITERAL      -> POS_INT_LITERAL | POS_FLOAT_LITERAL
// POS_INT_LITERAL      -> int_const_dec | int_const_hex
// POS_FLOAT_LITERAL    -> float_const

// TYPE                 -> BUILT_IN_TYPE | ARRAY_TYPE | MAP_TYPE | USER_TYPE_REF
// BUILT_IN_TYPE        -> SIMPLE_TYPE | STRING_TYPE | HANDLE_TYPE
// SIMPLE_TYPE          -> bool | FLOAT_TYPE | INTEGER_TYPE
// FLOAT_TYPE           -> float | double
// HANDLE_TYPE          -> handle langle [HANDLE_KIND] rangle [qstn]
// HANDLE_KIND          -> message_pipe | data_pipe_consumer | data_pipe_producer | shared_buffer
// INTEGER_TYPE         -> int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
// STRING_TYPE          -> string [qstn]
// ARRAY_TYPE           -> array langle TYPE [comma int_const_dec] rangle [qstn]
// MAP_TYPE             -> map langle MAP_KEY_TYPE comma TYPE rangle [qstn]
// MAP_KEY_TYPE         -> SIMPLE_TYPE | string | ENUM_TYPE
// USER_TYPE_REF        -> INTERFACE_TYPE | STRUCT_TYPE | UNION_TYPE | ENUM_TYPE
// INTERFACE_TYPE       -> IDENTIFIER [amp] [qstn] {{where IDENTIFIER resolves to an interface}}
// STRUCT_TYPE          -> IDENTIFIER [qstn] {{where IDENTIFIER resolves to a struct}}
// UNION_TYPE           -> IDENTIFIER [qstn] {{where IDENTIFIER resolves to a union}}
// ENUM_TYPE            -> IDENTIFIER  {{where IDENTIFIER resolves to an enum}}

// IDENTIFIER           -> name {dot name}

////////////////////////////////////////////////////////////////////////////
// parseX() methods follow.
////////////////////////////////////////////////////////////////////////////

// Note about the input and output of the parseX() methods: The method
// Parser.OK() indicates whether or not there has been a parsing error.
// All of the methods start with the check:
//	if !p.OK()
//		return
//	}
// and sometimes perform this check midway through their logic too. To make
// this more concise some of the methods return the value of Parser.OK() so that
// a caller can check the value without an additional 'if' clause. If a parseX()
// method has no other value it needs to return it always returns the value of
// Parser.OK().
//
// Many of the methods construct a Mojom object and return it. For example
// parseInterfaceDecl() returns a MojomInterface. If the method is responsible
// for parsing a block containing arbitrarily many elements then instead the
// method is passed a container that it fills up. For example
// parseInterfaceBody() is passed a MojomInterface that it fills up and it
// returns the bool Parser.OK(). If a Mojom object can take optional attributes
// then the attributes are parsed first via parseAttributes() and then the
// attributes are passed into the method that parses the object. For example
// parseInterfaceDecl() takes the parameter attributes *mojom.Attributes.
//
// Some of the method names start with the word "try": for example tryParseArrayType().
// The word "try" in the name is a hint that the corresponding structure to
// be parsed may or may not occur next and there should be no error if
// it turns out the production does not match. For example tryParseArrayType()
// returns a TypeRef that will be non-nil just in case an ARRAY_TYPE was
// successfully parsed. But if it turns out that the token "array" does not occur
// next then it is not an error and tryParseArrayType() simply returns nil without
// setting an error condition.
//
// The helper methods that read in the terminals of the grammar are given
// names of the form readFoo() instead of parseFoo(). For example there is a
// method readName() whose job is to read a name. This method is not called
// parseName() because name is a terminal of our grammar.

// ATTR_MOJOM_FILE  -> [ATTRIBUTES] MOJOM_FILE
// MOJOM_FILE       -> MODULE_DECL {IMPORT_STMNT} {ATTR_MOJOM_DECL}
// MOJOM_FILE       -> IMPORT_STMNT {IMPORT_STMNT} {ATTR_MOJOM_DECL}
// MOJOM_FILE       -> MOJOM_DECL {ATTR_MOJOM_DECL}
//
// Returns Parser.OK()
func (p *Parser) parseMojomFile() bool {
	p.pushRootNode("MojomFile")
	defer p.popNode()

	initialAttributes := p.parseAttributes()

	moduleNamespace := p.parseModuleDecl()

	if !p.OK() {
		return false
	}

	if moduleNamespace.Identifier != "" {
		p.mojomFile.Attributes = initialAttributes
		initialAttributes = nil
	}

	// Set up the root scope
	p.pushScope(p.mojomFile.InitializeFileScope(moduleNamespace))
	defer p.popScope()

	if p.checkEOF() {
		if initialAttributes != nil && moduleNamespace.Identifier == "" {
			message := "The .mojom file contains an attributes section but nothing else."
			p.parseError(ParserErrorCodeBadAttributeLocation, message)
			return false
		}
		// Accept an empty .mojom file.
		return true
	}

	importedFiles := p.parseImportStatements()
	if !p.OK() {
		return false
	}
	for _, importedFile := range importedFiles {
		p.mojomFile.AddImport(importedFile)
	}

	if moduleNamespace.Identifier == "" && len(importedFiles) > 0 && initialAttributes != nil {
		message := "Attributes are not allowed before an import statement."
		p.parseError(ParserErrorCodeBadAttributeLocation, message)
		return false
	}

	attributes := p.parseAttributes()
	if !p.OK() {
		return false
	}
	if initialAttributes != nil {
		if attributes != nil {
			// This is impossible because parseModuleDecl() would have complained
			// about not expecting to see a "[".
			panic("Internal logic error.")
		} else {
			attributes = initialAttributes
		}
	}

	// ATTR_MOJOM_DECL  -> [ATTRIBUTES] MOJOM_DECL
	// MOJOM_DECL       -> INTRFC_DECL | STRUCT_DECL | UNION_DECL | ENUM_DECL | CONSTANT_DECL
	for ; ; attributes = p.parseAttributes() {
		if !p.OK() {
			return false
		}
		if p.checkEOF() {
			if attributes != nil {
				message := "File ends with extraneouss attributes."
				p.parseError(ParserErrorCodeBadAttributeLocation, message)
			}
			return false
		}
		nextToken := p.peekNextToken("")
		var duplicateNameError error = nil
		switch nextToken.Kind {
		case lexer.Interface:
			if mojomInterface := p.parseInterfaceDecl(attributes); mojomInterface != nil {
				duplicateNameError = p.mojomFile.AddInterface(mojomInterface)
			}
		case lexer.Struct:
			if mojomStruct := p.parseStructDecl(attributes); mojomStruct != nil {
				duplicateNameError = p.mojomFile.AddStruct(mojomStruct)
			}
		case lexer.Union:
			if mojomUnion := p.parseUnionDecl(attributes); mojomUnion != nil {
				duplicateNameError = p.mojomFile.AddUnion(mojomUnion)
			}
		case lexer.Enum:
			if mojomEnum := p.parseEnumDecl(attributes); mojomEnum != nil {
				duplicateNameError = p.mojomFile.AddEnum(mojomEnum)
			}
		case lexer.Const:
			if constant := p.parseConstDecl(attributes); constant != nil {
				duplicateNameError = p.mojomFile.AddConstant(constant)
			}
		default:
			p.unexpectedTokenError(nextToken, "interface, struct, union, enum or const")
			return false
		}

		if p.OK() && duplicateNameError != nil {
			p.err = duplicateNameError
			return false
		}
	}
	return p.OK()
}

// ATTRIBUTES      -> lbracket ATTR_ASSIGNMENT { comma, ATTR_ASSIGNMENT}
// ATTR_ASSIGNMENT -> name equals name | name equals literal
func (p *Parser) parseAttributes() (attributes *mojom.Attributes) {
	if !p.OK() {
		return
	}

	if !p.tryMatch(lexer.LBracket) {
		// There is no attributes section here
		return
	}

	p.pushChildNode("attributes")
	defer p.popNode()

	attributes = mojom.NewAttributes(p.lastConsumed)

	nextToken := p.lastConsumed
	for nextToken.Kind != lexer.RBracket {
		key := p.readName()
		keyToken := p.lastConsumed
		p.attachToken()
		if !p.OK() {
			return
		}
		if !p.match(lexer.Equals) {
			return
		}

		var value mojom.LiteralValue
		if p.peekNextToken("Expecting to find an attribute value.").Kind == lexer.Name {
			text := p.readName()
			// TODO(rudominer) Decide if we support attribute values as Names.
			// Currently we convert a name into a string literal here.
			//      See https://github.com/domokit/mojo/issues/561
			value = mojom.MakeStringLiteralValue(text)
		} else {
			value = p.parseLiteral()
		}
		p.attachToken()

		if !p.OK() {
			return
		}
		attributes.List = append(attributes.List, mojom.NewMojomAttribute(key, &keyToken, value))

		nextToken = p.peekNextToken("I was reading an attributes section.")
		if !p.OK() {
			return
		}
		p.consumeNextToken()
		if nextToken.Kind != lexer.RBracket && nextToken.Kind != lexer.Comma {
			switch nextToken.Kind {
			case lexer.Module, lexer.Interface, lexer.Struct, lexer.Union, lexer.Enum:
				message := fmt.Sprintf("The attribute section is missing a closing ] before %s.", nextToken)
				p.parseErrorT(ParserErrorCodeUnexpectedToken, message, nextToken)
				return
			default:
				p.unexpectedTokenError(nextToken, "comma or ]")
				return
			}
		}
	}

	return
}

//MODULE_DECL -> module identifier semi
//
// parseModuleDecl returns a pointer to a ModuleNamespace. If there is not a
// module declaration, its Identifier is an empty string. Check p.OK() for errors.
func (p *Parser) parseModuleDecl() (moduleNamespace *mojom.ModuleNamespace) {
	moduleNamespace = mojom.NewModuleNamespace("", nil)
	if !p.OK() {
		return
	}
	if p.checkEOF() {
		return
	}
	nextToken := p.peekNextToken("No Mojom declarations found.")
	if !p.OK() {
		return
	}
	switch nextToken.Kind {
	case lexer.Module:
		p.consumeNextToken() // Consume the MODULE token.
		break
	case lexer.Import, lexer.Interface, lexer.Struct, lexer.Union, lexer.Enum, lexer.Const:
		return // There is no module declaration.
	default:
		p.unexpectedTokenError(nextToken, "module, import, interface, struct, union, enum or constant")
		return
	}

	p.pushChildNode("moduleDecl")
	defer p.popNode()

	moduleIdentifier, identifierToken := p.parseIdentifier()
	moduleNamespace.Identifier = moduleIdentifier
	moduleNamespace.Token = &identifierToken
	p.matchSemicolon()
	return
}

// IMPORT_STMNT  -> import string_literal
//
// Returns a non-nil, but possibly empty, slice of ImportedFiles.
func (p *Parser) parseImportStatements() (imports []*mojom.ImportedFile) {
	imports = make([]*mojom.ImportedFile, 0)
	if !p.OK() {
		return
	}

	nextToken := p.peekNextToken("")
	if !p.OK() {
		return
	}
	for nextToken.Kind == lexer.Import {
		p.pushChildNode("importStmnt")
		defer p.popNode()

		p.consumeNextToken() // consume the IMPORT token.

		fileName := p.readStringLiteral()
		fileNameToken := p.lastConsumed
		p.attachToken()
		if !p.OK() {
			return
		}

		if !p.matchSemicolon() {
			return
		}

		imports = append(imports, mojom.NewImportedFile(fileName, &fileNameToken))

		if p.checkEOF() {
			// Allow a .mojom file containing only import statements.
			return
		}
		nextToken = p.peekNextToken("")
		if !p.OK() {
			return
		}
	}

	switch nextToken.Kind {
	case lexer.Module:
		message := "The module declaration must come before the import statements."
		p.parseError(ParserErrorCodeUnexpectedToken, message)
		return
	case lexer.Interface, lexer.Struct, lexer.Union, lexer.Enum, lexer.Const, lexer.LBracket:
		return
	default:
		p.unexpectedTokenError(nextToken, "import, attributes, interface, struct, union, enum or constant")
		return
	}
}

// INTRFC_DECL  -> interface name lbrace INTRFC_BODY rbrace semi
func (p *Parser) parseInterfaceDecl(attributes *mojom.Attributes) (mojomInterface *mojom.MojomInterface) {
	if !p.OK() {
		return
	}
	p.pushChildNode("interfaceDecl")
	defer p.popNode()

	if !p.match(lexer.Interface) {
		return
	}

	simpleName := p.readName()
	if !p.OK() {
		return
	}
	nameToken := p.lastConsumed
	mojomInterface = mojom.NewMojomInterface(p.DeclData(simpleName, nameToken, attributes))

	if !p.match(lexer.LBrace) {
		return
	}

	if !p.parseInterfaceBody(mojomInterface) {
		return
	}

	if !p.match(lexer.RBrace) {
		return
	}

	p.matchSemicolon()

	return
}

// INTRFC_BODY          -> {ATTR_INTRFC_ELEMENT}
// ATTR_INTRFC_ELEMENT  -> [ATTRIBUTES] INTRFC_ELEMENT
// INTRFC_ELEMENT       -> METHOD_DECL | ENUM_DECL | CONSTANT_DECL
func (p *Parser) parseInterfaceBody(mojomInterface *mojom.MojomInterface) bool {
	if !p.OK() {
		return p.OK()
	}
	p.pushChildNode("interfaceBody")
	defer p.popNode()

	// The interface body forms a new scope.
	p.pushScope(mojomInterface.InitAsScope(p.currentScope))
	defer p.popScope()

	rbraceFound := false
	for attributes := p.parseAttributes(); !rbraceFound; attributes = p.parseAttributes() {
		if !p.OK() {
			return false
		}
		nextToken := p.peekNextToken("I was parsing an interface body.")
		var duplicateNameError error = nil
		switch nextToken.Kind {
		case lexer.Name:
			if method := p.parseMethodDecl(attributes); p.OK() {
				duplicateNameError = mojomInterface.AddMethod(method)
				break
			}
			return false
		case lexer.Enum:
			if mojomEnum := p.parseEnumDecl(attributes); mojomEnum != nil {
				duplicateNameError = mojomInterface.AddEnum(mojomEnum)
			}
		case lexer.Const:
			if constant := p.parseConstDecl(attributes); constant != nil {
				duplicateNameError = mojomInterface.AddConstant(constant)
			}
		case lexer.RBrace:
			rbraceFound = true
			if attributes != nil {
				message := "Interface body ends with extraneouss attributes."
				p.parseError(ParserErrorCodeBadAttributeLocation, message)
			}
			break
		default:
			p.unexpectedTokenError(nextToken, "union, enum, const or an identifier")
			return false
		}
		if p.OK() && duplicateNameError != nil {
			p.err = duplicateNameError
			return false
		}
	}
	if p.OK() {
		if err := mojomInterface.ComputeMethodOrdinals(); err != nil {
			p.err = err
			return false
		}
	}
	return p.OK()
}

// METHOD_DECL -> name [ordinal] lparen [PARAM_LIST] rparen [response lparen [PARAM_LIST] rparen]semi
func (p *Parser) parseMethodDecl(attributes *mojom.Attributes) *mojom.MojomMethod {
	if !p.OK() {
		return nil
	}
	p.pushChildNode("methodDecl")
	defer p.popNode()

	methodName := p.readName()
	nameToken := p.lastConsumed
	if !p.OK() {
		return nil
	}

	ordinalValue, err := p.readOrdinal()
	if err != nil {
		p.invalidOrdinalError("method", methodName, nameToken, err)
		return nil
	}

	if !p.match(lexer.LParen) {
		return nil
	}

	params := p.parseParamList(methodName, true)
	if !p.OK() {
		return nil
	}

	if !p.match(lexer.RParen) {
		return nil
	}
	parenBeforeSemicolon := p.lastConsumed

	// Check for a response message
	var responseParams *mojom.MojomStruct = nil
	if p.tryMatch(lexer.Response) {
		if !p.match(lexer.LParen) {
			return nil
		}

		responseParams = p.parseParamList(methodName, false)
		if !p.OK() {
			return nil
		}

		if !p.match(lexer.RParen) {
			return nil
		}
		parenBeforeSemicolon = p.lastConsumed
	}

	if !p.matchSemicolonToken(parenBeforeSemicolon) {
		return nil
	}

	declData := p.DeclDataWithOrdinal(methodName, nameToken, attributes, ordinalValue)
	mojomMethod := mojom.NewMojomMethod(declData, params, responseParams)
	return mojomMethod
}

// PARAM_LIST -> PARAM_DECL {, PARAM_DECL}
// PARAM_DECL -> [ATTRIBUTES] TYPE name [ordinal]
//
// Returns a MojomStruct containing the list of parameters. This may
// be nil in case of an early error. Check Parser.OK().
func (p *Parser) parseParamList(methodName string, isRequest bool) (paramStruct *mojom.MojomStruct) {
	if !p.OK() {
		return nil
	}
	p.pushChildNode("paramList")
	defer p.popNode()

	if isRequest {
		paramStruct = mojom.NewSyntheticRequestStruct(methodName, lexer.Token{}, p.mojomFile)
	} else {
		paramStruct = mojom.NewSyntheticResponseStruct(methodName, lexer.Token{}, p.mojomFile)
	}
	nextToken := p.peekNextToken("I was parsing method parameters.")
	for nextToken.Kind != lexer.RParen {

		attributes := p.parseAttributes()
		fieldType := p.parseType()
		if !p.OK() {
			return
		}
		name := p.readName()
		nameToken := p.lastConsumed

		if !p.OK() {
			return
		}

		ordinalValue, err := p.readOrdinal()
		if err != nil {
			p.invalidOrdinalError("parameter", name, nameToken, err)
			return
		}

		declData := p.DeclDataWithOrdinal(name, nameToken, attributes, ordinalValue)
		if duplicateNameError := paramStruct.AddField(mojom.NewStructField(
			declData, fieldType, nil)); duplicateNameError != nil {
			p.err = duplicateNameError
			return nil
		}

		nextToken = p.peekNextToken("I was parsing method parameters.")
		switch nextToken.Kind {
		case lexer.Comma:
			p.consumeNextToken()
			continue
		case lexer.RParen:
			continue
		default:
			p.unexpectedTokenError(nextToken, "comma or )")
			return nil
		}
	}

	if p.OK() {
		paramStruct.ComputeFieldOrdinals()
	}
	return
}

// STRUCT_DECL   -> struct name lbrace STRUCT_BODY rbrace semi
func (p *Parser) parseStructDecl(attributes *mojom.Attributes) (mojomStruct *mojom.MojomStruct) {
	if !p.OK() {
		return
	}
	p.pushChildNode("structDecl")
	defer p.popNode()

	if !p.match(lexer.Struct) {
		return
	}

	simpleName := p.readName()
	p.attachToken()
	if !p.OK() {
		return
	}
	nameToken := p.lastConsumed
	mojomStruct = mojom.NewMojomStruct(p.DeclData(simpleName, nameToken, attributes))

	if !p.match(lexer.LBrace) {
		return
	}

	if !p.parseStructBody(mojomStruct) {
		return
	}

	if !p.match(lexer.RBrace) {
		return
	}

	p.matchSemicolon()

	return
}

// STRUCT_BODY          -> {ATTR_STRUCT_ELEMENT}
// ATTR_STRUCT_ELEMENT  -> [ATTRIBUTES] STRUCT_ELEMENT
// STRUCT_ELEMENT       -> STRUCT_FIELD | ENUM_DECL | CONSTANT_DECL
func (p *Parser) parseStructBody(mojomStruct *mojom.MojomStruct) bool {
	if !p.OK() {
		return p.OK()
	}
	p.pushChildNode("structBody")
	defer p.popNode()

	// The struct body forms a new scope.
	p.pushScope(mojomStruct.InitAsScope(p.currentScope))
	defer p.popScope()

	rbraceFound := false
	for attributes := p.parseAttributes(); !rbraceFound; attributes = p.parseAttributes() {
		if !p.OK() {
			return false
		}
		nextToken := p.peekNextToken("I was parsing a struct body.")
		var duplicateNameError error = nil
		switch nextToken.Kind {
		case lexer.Name:
			if field := p.parseStructField(attributes); field != nil {
				duplicateNameError = mojomStruct.AddField(field)
			}
		case lexer.Enum:
			if mojomEnum := p.parseEnumDecl(attributes); mojomEnum != nil {
				duplicateNameError = mojomStruct.AddEnum(mojomEnum)
			}
		case lexer.Const:
			if constant := p.parseConstDecl(attributes); constant != nil {
				duplicateNameError = mojomStruct.AddConstant(constant)
			}
		case lexer.RBrace:
			rbraceFound = true
			if attributes != nil {
				message := "Struct body ends with extraneouss attributes."
				p.parseError(ParserErrorCodeBadAttributeLocation, message)
			}
			break
		default:
			p.unexpectedTokenError(nextToken, "field, enum or constant declaration")
			return false
		}
		if p.OK() && duplicateNameError != nil {
			p.err = duplicateNameError
			return false
		}
	}
	if p.OK() {
		mojomStruct.ComputeFieldOrdinals()
	}
	return p.OK()
}

// STRUCT_FIELD         -> TYPE name [ordinal] [equals DEFAULT_VALUE] semi
// DEFAULT_VALUE        -> COMPATIBLE_VALUE_REF | default
func (p *Parser) parseStructField(attributes *mojom.Attributes) *mojom.StructField {
	if !p.OK() {
		return nil
	}
	p.pushChildNode("structField")
	defer p.popNode()

	fieldType := p.parseType()
	fieldName := p.readName()
	nameToken := p.lastConsumed
	p.attachToken()

	ordinalValue, err := p.readOrdinal()
	if err != nil {
		p.invalidOrdinalError("field", fieldName, nameToken, err)
		return nil
	}

	var defaultValue mojom.ValueRef
	var defaultValueToken lexer.Token
	defaultKeywordUsed := false
	if p.tryMatch(lexer.Equals) {
		defaultValueToken = p.peekNextToken("Expecting a default value.")
		if defaultValueToken.Kind == lexer.Default {
			p.consumeNextToken()
			defaultValue = mojom.MakeDefaultLiteral()
			defaultKeywordUsed = true
		} else {
			assigneeSpec := mojom.AssigneeSpec{
				fieldName,
				fieldType,
			}
			defaultValue = p.parseValue(assigneeSpec)
		}
	}
	if !p.matchSemicolon() {
		return nil
	}

	declData := p.DeclDataWithOrdinal(fieldName, nameToken, attributes, ordinalValue)
	field := mojom.NewStructField(declData, fieldType, defaultValue)
	if !field.ValidateDefaultValue() {
		var message string
		if defaultKeywordUsed {
			message = fmt.Sprintf("Illegal assignment: The 'default' keyword may not be used with the field %s of type %s.",
				fieldName, fieldType.TypeName())
		} else {
			valueString := fmt.Sprintf("%v", defaultValue)
			valueTypeString := ""
			concreteValue := defaultValue.ResolvedConcreteValue()
			if concreteValue != nil {
				valueString = fmt.Sprintf("%v", concreteValue)
				valueTypeString = fmt.Sprintf(" of type %s", concreteValue.ValueType())
			}
			message = fmt.Sprintf("Illegal assignment: Field %s of type %s may not be assigned the value %s%s.",
				fieldName, fieldType.TypeName(), valueString, valueTypeString)
		}
		p.parseErrorT(ParserErrorCodeNotAssignmentCompatible, message, defaultValueToken)
		return nil
	}

	return field
}

// UNION_DECL    -> union name lbrace UNION_BODY rbrace semi
func (p *Parser) parseUnionDecl(attributes *mojom.Attributes) (union *mojom.MojomUnion) {
	if !p.OK() {
		return
	}
	p.pushChildNode("unionDecl")
	defer p.popNode()

	if !p.match(lexer.Union) {
		return
	}

	simpleName := p.readName()
	p.attachToken()
	if !p.OK() {
		return
	}
	nameToken := p.lastConsumed
	union = mojom.NewMojomUnion(p.DeclData(simpleName, nameToken, attributes))

	if !p.match(lexer.LBrace) {
		return
	}

	if !p.parseUnionBody(union) {
		return
	}

	if !p.match(lexer.RBrace) {
		return
	}

	if p.matchSemicolon() {
		union.ComputeFieldTags()
	}

	return
}

// UNION_BODY         -> {UNION_FIELD_DECL}
// UNION_FIELD_DECL   -> [ATTRIBUTES] TYPE name [ordinal] semi
func (p *Parser) parseUnionBody(union *mojom.MojomUnion) bool {
	if !p.OK() {
		return p.OK()
	}
	p.pushChildNode("unionBody")
	defer p.popNode()

	rbraceFound := false
	for attributes := p.parseAttributes(); !rbraceFound; attributes = p.parseAttributes() {
		if !p.OK() {
			return false
		}
		nextToken := p.peekNextToken("I was parsing a union body.")
		switch nextToken.Kind {
		case lexer.Name:
			fieldType := p.parseType()
			fieldName := p.readName()
			nameToken := p.lastConsumed

			tag, err := p.readOrdinal()
			if err != nil {
				p.invalidOrdinalError("union field", fieldName, nameToken, err)
				return false
			}

			if !p.matchSemicolon() {
				return false
			}
			if duplicateNameError := union.AddField(p.DeclDataWithOrdinal(
				fieldName, nameToken, attributes, tag), fieldType); duplicateNameError != nil {
				p.err = duplicateNameError
				return false

			}
		case lexer.RBrace:
			rbraceFound = true
			if attributes != nil {
				message := "Enum body ends with extraneouss attributes."
				p.parseError(ParserErrorCodeBadAttributeLocation, message)
			}
			break
		default:
			p.unexpectedTokenError(nextToken, "either another union field or }")
			return false
		}
	}
	return p.OK()
}

// ENUM_DECL -> enum name lbrace ENUM_BODY rbrace semi
func (p *Parser) parseEnumDecl(attributes *mojom.Attributes) (enum *mojom.MojomEnum) {
	if !p.OK() {
		return
	}
	p.pushChildNode("enumDecl")
	defer p.popNode()

	if !p.match(lexer.Enum) {
		return
	}

	simpleName := p.readName()
	p.attachToken()
	if !p.OK() {
		return
	}
	nameToken := p.lastConsumed
	enum = mojom.NewMojomEnum(p.DeclData(simpleName, nameToken, attributes))

	if !p.match(lexer.LBrace) {
		return
	}

	if !p.parseEnumBody(enum) {
		return
	}

	if !p.match(lexer.RBrace) {
		return
	}

	p.matchSemicolon()

	return
}

// ENUM_BODY     -> [ ENUN_VALUE {, ENUM_VALUE} [,] ]
// ENUM_VALUE    -> [ATTRIBUTES] name [equals ENUM_VAL_INITIALIZER]
func (p *Parser) parseEnumBody(mojomEnum *mojom.MojomEnum) bool {
	if !p.OK() {
		return p.OK()
	}
	p.pushChildNode("enumBody")
	defer p.popNode()

	// The enum body forms a new scope in which it's enun values are defined.
	p.pushScope(mojomEnum.InitAsScope(p.currentScope))
	defer p.popScope()

	rbraceFound := false
	trailingCommaFound := false
	firstValue := true
	for attributes := p.parseAttributes(); !rbraceFound; attributes = p.parseAttributes() {
		if !p.OK() {
			return false
		}
		nextToken := p.peekNextToken("I was parsing an enum body.")
		var duplicateNameError error = nil
		switch nextToken.Kind {
		case lexer.Name:
			if !firstValue && !trailingCommaFound {
				message := fmt.Sprintf("Expecting a comma after %s before the next value %s.",
					p.lastConsumed, nextToken)
				p.parseErrorT(ParserErrorCodeUnexpectedToken, message, p.lastConsumed)
				return false
			}
			firstValue = false
			name := p.readName()
			p.attachToken()
			nameToken := p.lastConsumed
			var valueRef mojom.ValueRef
			if p.tryMatch(lexer.Equals) {
				valueRef = p.parseEnumValueInitializer(mojomEnum, name)
			}
			declData := p.DeclData(name, nameToken, attributes)
			duplicateNameError = mojomEnum.AddEnumValue(declData, valueRef)
			trailingCommaFound = p.tryMatch(lexer.Comma)
		case lexer.RBrace:
			rbraceFound = true
			if attributes != nil {
				message := "Enum body ends with extraneouss attributes."
				p.parseError(ParserErrorCodeBadAttributeLocation, message)
			}
			break
		case lexer.Comma:
			break
		default:
			p.unexpectedTokenError(nextToken, "either another enum value or }")
			return false
		}
		if p.OK() && duplicateNameError != nil {
			p.err = duplicateNameError
			return false
		}
	}
	return p.OK()
}

// ENUM_VAL_INITIALIZER -> INT32_VAL | APPROPRIATE_ENUM_VALUE_REF
func (p *Parser) parseEnumValueInitializer(mojoEnum *mojom.MojomEnum, valueName string) mojom.ValueRef {
	if !p.OK() {
		return nil
	}
	p.pushChildNode("enumValueInitializer")
	defer p.popNode()

	// We need to manufacture an instance of Type to act as the "assigneeType"
	// for the new ValueSpec we are creating. This is because unlike
	// other types of value assignment, an enum value initializer is not
	// preceded by a type reference for the assignee. Rather the type of
	// the assignee is implicit in the scope.
	enumType := mojom.NewResolvedUserTypeRef(mojoEnum.FullyQualifiedName(), mojoEnum)

	valueToken := p.peekNextToken("Parsing an enum value initializer type.")
	valueRef := p.parseValue(mojom.AssigneeSpec{valueName, enumType})
	if valueRef == nil {
		return nil
	}
	if !valueRef.MarkUsedAsEnumValueInitializer() {
		message := fmt.Sprintf("Illegal value: %s. An enum value initializer must be a signed 32-bit integer value.",
			valueToken)
		p.parseErrorT(ParserErrorCodeUnexpectedToken, message, valueToken)
		return nil
	}

	return valueRef
}

// CONSTANT_DECL -> const CONST_OK_TYPE name equals COMPATIBLE_VALUE_REF semi
// CONST_OK_TYPE -> SIMPLE_TYPE | string | ENUM_TYPE
func (p *Parser) parseConstDecl(attributes *mojom.Attributes) (constant *mojom.UserDefinedConstant) {
	if !p.OK() {
		return
	}

	p.pushChildNode("constDecl")
	defer p.popNode()

	p.match(lexer.Const)
	declaredTypeToken := p.peekNextToken("Parsing a type.")
	declaredType := p.parseType()
	name := p.readName()
	if !p.OK() {
		return
	}
	nameToken := p.lastConsumed
	p.match(lexer.Equals)
	valueToken := p.peekNextToken("Parsing a value.")
	assigneeSpec := mojom.AssigneeSpec{
		name,
		declaredType,
	}
	value := p.parseValue(assigneeSpec)
	if !p.OK() {
		return
	}

	if !declaredType.MarkUsedAsConstantType() {
		message := fmt.Sprintf("The type %s is not allowed as the type of a declared constant. "+
			"Only simple types, strings and enum types may be the types of constants.", declaredType)
		p.parseErrorT(ParserErrorCodeUnexpectedToken, message, declaredTypeToken)
		return
	}

	constant = mojom.NewUserDefinedConstant(p.DeclData(name, nameToken, attributes), declaredType, value)
	p.matchSemicolon()

	if !constant.ValidateValue() {
		valueString := fmt.Sprintf("%v", value)
		valueTypeString := ""
		concreteValue := value.ResolvedConcreteValue()
		if concreteValue != nil {
			valueString = fmt.Sprintf("%v", concreteValue)
			valueTypeString = fmt.Sprintf(" of type %s", concreteValue.ValueType())
		}
		message := fmt.Sprintf("Illegal assignment: Constant %s of type %s may not be assigned the value %s%s.",
			name, declaredType.TypeName(), valueString, valueTypeString)
		p.parseErrorT(ParserErrorCodeNotAssignmentCompatible, message, valueToken)
		return
	}

	return
}

// VALUE_REF -> USER_VALUE_REF | LITERAL_VALUE | BUILT_IN_FLOAT_CONST
func (p *Parser) parseValue(assigneeSpec mojom.AssigneeSpec) mojom.ValueRef {
	if !p.OK() {
		return nil
	}
	p.pushChildNode("value")
	defer p.popNode()

	nextToken := p.peekNextToken("I was parsing a value.")
	p.attachToken()
	if nextToken.Kind == lexer.Name {
		// Note that we do not distinguish between a USER_VALUE_REF and a
		// BUILT_IN_FLOAT_CONST at parsing time. At this stage we consider both
		// to be a UserValueRef. Only at resolution time do we decide if it
		// turns out to be a BUILT_IN_FLOAT_CONST.
		return p.parseUserValueRef(assigneeSpec)
	}
	literalValue := p.parseLiteral()
	p.attachToken()
	if !p.OK() || literalValue.ValueType() == nil {
		return nil
	}
	return literalValue
}

//LITERAL_VALUE  -> BOOL_LITERAL | string_literal | NUMBER_LITERAL
// BOOL_LITERAL  -> true | false
func (p *Parser) parseLiteral() mojom.LiteralValue {
	if !p.OK() {
		return mojom.LiteralValue{}
	}
	p.pushChildNode("literal")
	defer p.popNode()

	nextToken := p.peekNextToken("I was parsing a literal.")
	switch nextToken.Kind {
	case lexer.StringLiteral:
		return mojom.MakeStringLiteralValue(p.readStringLiteral())
	case lexer.True:
		p.consumeNextToken()
		return mojom.MakeBoolLiteralValue(true)
	case lexer.False:
		p.consumeNextToken()
		return mojom.MakeBoolLiteralValue(false)
	case lexer.Plus, lexer.Minus, lexer.FloatConst, lexer.IntConstDec, lexer.IntConstHex:
		return p.parseNumberLiteral()

	default:
		p.unexpectedTokenError(nextToken, "a string, numeric or boolean literal")
		return mojom.LiteralValue{}
	}
}

// NUMBER_LITERAL       -> [plus | minus] POS_NUM_LITERAL
// POS_NUM_LITERAL      -> POS_INT_LITERAL | POS_FLOAT_LITERAL
func (p *Parser) parseNumberLiteral() mojom.LiteralValue {
	if !p.OK() {
		return mojom.LiteralValue{}
	}
	p.pushChildNode("numberLiteral")
	defer p.popNode()

	initialMinus := p.tryMatch(lexer.Minus)
	initialPlus := p.tryMatch(lexer.Plus)
	if initialMinus && initialPlus {
		p.unexpectedTokenError(p.lastConsumed, "a number")
		return mojom.LiteralValue{}
	}

	nextToken := p.peekNextToken("I was parsing a numberliteral.")
	switch nextToken.Kind {
	case lexer.IntConstDec, lexer.IntConstHex:
		absoluteValue, numBits, signed, ok := p.parsePositiveIntegerLiteral(initialMinus, true, !initialMinus, 64)
		if !ok {
			return mojom.LiteralValue{}
		}
		var value int64
		if signed {
			value = int64(absoluteValue)
			if initialMinus {
				value = -1 * value
			}
		}
		switch numBits {
		case 8:
			if signed {
				return mojom.MakeInt8LiteralValue(int8(value))
			} else {
				return mojom.MakeUint8LiteralValue(uint8(absoluteValue))
			}
		case 16:
			if signed {
				return mojom.MakeInt16LiteralValue(int16(value))
			} else {
				return mojom.MakeUint16LiteralValue(uint16(absoluteValue))
			}
		case 32:
			if signed {
				return mojom.MakeInt32LiteralValue(int32(value))
			} else {
				return mojom.MakeUint32LiteralValue(uint32(absoluteValue))
			}
		case 64:
			if signed {
				return mojom.MakeInt64LiteralValue(value)
			} else {
				return mojom.MakeUint64LiteralValue(absoluteValue)
			}
		default:
			panic(fmt.Sprintf("Unexpected value for numBits: %d", numBits))
		}
	case lexer.FloatConst:
		value, _ := p.parsePositiveFloatLiteral(initialMinus)
		return mojom.MakeDoubleLiteralValue(value)

	default:
		p.unexpectedTokenError(nextToken, "a number")
		return mojom.LiteralValue{}
	}
}

// IDENTIFIER   -> name {dot name}
func (p *Parser) parseIdentifier() (identifier string, firstToken lexer.Token) {
	if !p.OK() {
		return
	}
	p.pushChildNode("identifier")
	defer p.popNode()

	firstToken = p.peekNextToken("Expecting an identifier.")
	if !p.OK() {
		return
	}
	if firstToken.Kind != lexer.Name {
		p.unexpectedTokenError(firstToken, "an identifier")
		return
	}

	for p.tryMatch(lexer.Name) {
		identifier += p.lastConsumed.Text
		if !p.tryMatch(lexer.Dot) {
			return
		}
		identifier += "."
	}
	message := fmt.Sprintf("Invalid identifier: %q. Identifiers may not end with a dot.", identifier)
	p.parseErrorT(ParserErrorCodeUnexpectedToken, message, firstToken)
	return
}

// TYPE -> BUILT_IN_TYPE | ARRAY_TYPE | MAP_TYPE | USER_TYPE_REF
func (p *Parser) parseType() mojom.TypeRef {
	if !p.OK() {
		return nil
	}
	p.pushChildNode("type")
	defer p.popNode()

	mojomType := p.tryParseBuiltInType()
	if mojomType == nil {
		mojomType = p.tryParseArrayType()
	}
	if mojomType == nil {
		mojomType = p.tryParseMapType()
	}
	if mojomType == nil {
		mojomType = p.parseTypeReference()
	}

	return mojomType
}

///////////////// Methods for parsing types and values ////////

// BUILT_IN_TYPE        -> SIMPLE_TYPE | STRING_TYPE | HANDLE_TYPE
// SIMPLE_TYPE          -> bool | FLOAT_TYPE | INTEGER_TYPE
// FLOAT_TYPE           -> float | double
// HANDLE_TYPE          -> handle langle [HANDLE_KIND] rangle [qstn]
// HANDLE_KIND          -> message_pipe | data_pipe_consumer | data_pipe_producer | shared_buffer
// INTEGER_TYPE         -> int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
// STRING_TYPE          -> string [qstn]
func (p *Parser) tryParseBuiltInType() mojom.TypeRef {
	if !p.OK() {
		return nil
	}

	typeNameToken := p.peekNextToken("I was reading a type.")
	if typeNameToken.Kind != lexer.Name {
		return nil
	}
	typeName := typeNameToken.Text
	builtInType := mojom.BuiltInType(typeName)
	if builtInType == nil {
		return nil
	}
	p.consumeNextToken()

	// handle<*> types
	if typeName == "handle" {
		if p.tryMatch(lexer.LAngle) {
			handleType := p.readText(lexer.Name)
			if !p.OK() {
				token := p.lastSeen
				p.unexpectedTokenError(token, "a type of handle")
				return nil
			}
			if p.match(lexer.RAngle) {
				typeName = fmt.Sprintf("%s<%s>", typeName, handleType)
				if builtInType = mojom.BuiltInType(typeName); builtInType == nil {
					message := fmt.Sprintf("Unrecognized type of handle: %s.", typeName)
					p.parseErrorT(ParserErrorCodeUnexpectedToken, message, typeNameToken)
					return nil
				}
			}
		}
		if !p.OK() {
			return nil
		}
	}

	// Check for nullable marker
	if p.tryMatch(lexer.Qstn) {
		if builtInType = mojom.BuiltInType(typeName + "?"); builtInType == nil {
			message := fmt.Sprintf("The type %s? is invalid because the type %s may not be made nullable.",
				typeName, typeName)
			p.parseErrorT(ParserErrorCodeUnexpectedToken, message, typeNameToken)
			return nil
		}
	}

	return builtInType
}

// ARRAY_TYPE  -> array langle TYPE [comma int_const_dec] rangle [qstn]
func (p *Parser) tryParseArrayType() mojom.TypeRef {
	if !p.OK() {
		return nil
	}

	nextToken := p.peekNextToken("Trying to read a type.")
	if nextToken.Kind != lexer.Name || nextToken.Text != "array" {
		return nil
	}
	p.consumeNextToken()
	if !p.match(lexer.LAngle) {
		return nil
	}

	elementType := p.parseType()
	if !p.OK() {
		return nil
	}

	isFixedSize := p.tryMatch(lexer.Comma)
	fixedSize := int32(-1)
	if isFixedSize {
		if size, _, _, ok := p.parsePositiveIntegerLiteral(false, false, false, 32); ok {
			fixedSize = int32(size)
		} else {
			return nil
		}

	}
	if !p.match(lexer.RAngle) {
		return nil
	}
	nullable := p.tryMatch(lexer.Qstn)

	return mojom.NewArrayTypeRef(elementType, fixedSize, nullable)
}

// MAP_TYPE      -> map langle MAP_KEY_TYPE comma TYPE rangle [qstn]
// MAP_KEY_TYPE  -> SIMPLE_TYPE | string | ENUM_TYPE
func (p *Parser) tryParseMapType() mojom.TypeRef {
	if !p.OK() {
		return nil
	}

	nextToken := p.peekNextToken("Trying to read a type.")
	if nextToken.Kind != lexer.Name || nextToken.Text != "map" {
		return nil
	}
	p.consumeNextToken()
	if !p.match(lexer.LAngle) {
		return nil
	}

	keyToken := p.peekNextToken("Trying to read a type.")
	keyType := p.parseType()
	p.match(lexer.Comma)
	valueType := p.parseType()
	if !p.match(lexer.RAngle) {
		return nil
	}
	nullable := p.tryMatch(lexer.Qstn)

	if !keyType.MarkUsedAsMapKey() {
		message := fmt.Sprintf("The type %s is not allowed as the key type of a map. "+
			"Only simple types, strings and enum types may be map keys.", keyType)
		p.parseErrorT(ParserErrorCodeUnexpectedToken, message, keyToken)
		return nil
	}

	return mojom.NewMapTypeRef(keyType, valueType, nullable)
}

// USER_TYPE_REF    -> INTERFACE_TYPE | STRUCT_TYPE | UNION_TYPE | ENUM_TYPE
// INTERFACE_TYPE   -> IDENTIFIER [amp] [qstn] {{where IDENTIFIER resolves to an interface}}
// STRUCT_TYPE      -> IDENTIFIER [qstn] {{where IDENTIFIER resolves to a struct}}
// UNION_TYPE       -> IDENTIFIER [qstn] {{where IDENTIFIER resolves to a union}}
// ENUM_TYPE        -> IDENTIFIER [qstn] {{where IDENTIFIER resolves to an interface}}
func (p *Parser) parseTypeReference() mojom.TypeRef {
	if !p.OK() {
		return nil
	}
	p.pushChildNode("typeReference")
	defer p.popNode()

	identifier, identifierToken := p.parseIdentifier()
	if !p.OK() {
		return nil
	}
	// Note we must check for '&' before we check for '?'.
	// The other order is invalid and if it occurrs the extraneous
	// '&' will be detected later.
	interfaceRequest := p.tryMatch(lexer.Amp)
	nullable := p.tryMatch(lexer.Qstn)
	if !p.OK() {
		return nil
	}
	typeReference := mojom.NewUserTypeRef(identifier, nullable,
		interfaceRequest, p.currentScope, identifierToken)
	p.mojomDescriptor.RegisterUnresolvedTypeReference(typeReference)
	return typeReference
}

// USER_VALUE_REF -> IDENTIFIER {{that resolves to an enum value or constant}}
func (p *Parser) parseUserValueRef(assigneeSpec mojom.AssigneeSpec) *mojom.UserValueRef {
	if !p.OK() {
		return nil
	}
	p.pushChildNode("userValueRef")
	defer p.popNode()

	identifier, identifierToken := p.parseIdentifier()
	if !p.OK() {
		return nil
	}
	valueReference := mojom.NewUserValueRef(assigneeSpec, identifier,
		p.currentScope, identifierToken)
	p.mojomDescriptor.RegisterUnresolvedValueReference(valueReference)
	return valueReference
}

// POS_INT_LITERAL -> int_const_dec | int_const_hex
//
// parsePositiveIntegerLiteral() parses the next token as an integer using the smallest
// size integer possible given the input constraints.
//
// |initialMinus| should the string to be parsed be prepended with an initial minus sign?
// If this is true then |allowUnsigned| must also be false.
//
// |acceptHex| should the string to be parsed be allowed to be expressed in "0x" notation?
//
// |allowUnsigned| If the string cannot be parsed into a signed integer with a certain number of
// bits then before trying a larger number of bits we will try an unsigned integer if this is true.
// If |allowUnsigned| is not true then the returned |signed| will never be false if |ok| is true.
//
// |maxNumBits| This value should be 8, 16, 32 or 64 and represents the maximum size of an integer
// variable into which the parsed value may fit. If |ok| is true then |numBits| <= |maxNumBits|.
//
// |absoluteValue| The absolute value of the parsed integer, stored in a uint64. If |ok|
// is true then the value, times -1 if |initialMinus| is true, is guaranteed to be
// convertible without loss to the signed or unsigned integer type given by |signed| and
// |numBits|. For example if |numBits| = 16 and |signed| is true and |initialMinus| is true
// then -1 * |absoluteValue| may be cast to an int16. If |numBits| = 64 and |signed| is false then
// |absoluteValue| may be cast to a uint64.
//
// |numBits| is the smalles number of bits, 8, 16, 32, or 64, that the parsed value
// may fit into. If |ok| is true then |numBits| <= |maxNumBits|.
//
// |signed| modifies |numBits| to indicate what type of integer variable the result may be cast to.
//
// |ok| If this is false then there was a parsing error stored in p.err.
func (p *Parser) parsePositiveIntegerLiteral(initialMinus, acceptHex, allowUnsigned bool, maxNumBits int) (absoluteValue uint64, numBits int, signed, ok bool) {
	p.pushChildNode("positive integer literal")
	defer p.popNode()

	if maxNumBits != 8 && maxNumBits != 16 && maxNumBits != 32 && maxNumBits != 64 {
		panic(fmt.Sprintf("maxNumBits must be 8, 16, 32 or 64: %d", maxNumBits))
	}

	if initialMinus && allowUnsigned {
		panic("If initialMinus is true then allowUnsigned must be false.")
	}

	nextToken := p.peekNextToken("I was parsing an integer literal.")
	p.consumeNextToken()
	intText := p.lastConsumed.Text

	// Set the base to 10 or 16.
	base := 10
	switch nextToken.Kind {
	case lexer.IntConstDec:
		break
	case lexer.IntConstHex:
		if !acceptHex {
			message := fmt.Sprintf("Illegal value: %s. Only a decimal integer literal is allowed here. "+
				"Hexadecimal is not valid.", nextToken)
			p.parseErrorT(ParserErrorCodeUnexpectedToken, message, nextToken)
			return
		}
		if len(intText) < 3 {
			message := fmt.Sprintf("Invalid hex integer literal: %q.", intText)
			p.parseErrorT(ParserErrorCodeIntegerParseError, message, nextToken)
			return
		}
		intText = intText[2:]
		base = 16

	default:
		p.unexpectedTokenError(nextToken, "a positive integer literal")
		return
	}

	// Add the initial minus sign if present.
	if initialMinus {
		intText = "-" + intText
	}

	var parseError error
	for _, numBits := range []int{8, 16, 32, 64} {
		if numBits > maxNumBits {
			break
		}
		// First try to parse as signed.
		signed = true
		intVal, err := strconv.ParseInt(intText, base, numBits)
		if err == nil {
			if intVal < 0 {
				intVal = -intVal
			}
			return uint64(intVal), numBits, signed, true
		}

		parseError = err
		// Then try unsigned.
		if allowUnsigned {
			signed = false
			intVal, err := strconv.ParseUint(intText, base, numBits)
			if err == nil {
				return intVal, numBits, signed, true
			}
			parseError = err
		}
	}

	switch parseError.(*strconv.NumError).Err {
	case strconv.ErrRange:
		message := fmt.Sprintf("Integer literal value out of range: %s.", intText)
		p.parseErrorT(ParserErrorCodeIntegerOutOfRange, message, nextToken)
	case strconv.ErrSyntax:
		panic(fmt.Sprintf("Lexer allowed unparsable integer literal: %s. "+
			"Kind = %s. error=%s.", nextToken.Text, nextToken.Kind, parseError))
	}
	return 0, 0, false, false
}

// POS_FLOAT_LITERAL  -> float_const
func (p *Parser) parsePositiveFloatLiteral(initialMinus bool) (float64, bool) {
	p.pushChildNode("positive float literal")
	defer p.popNode()

	nextToken := p.peekNextToken("I was parsing a float literal.")
	p.match(lexer.FloatConst)
	floatText := p.lastConsumed.Text
	if initialMinus {
		floatText = "-" + floatText
	}
	floatVal, err := strconv.ParseFloat(floatText, 64)
	if err == nil {
		return floatVal, true
	}
	switch err.(*strconv.NumError).Err {
	case strconv.ErrRange:
		message := fmt.Sprintf("Float literal value out of range: %s.", floatText)
		p.parseErrorT(ParserErrorCodeIntegerOutOfRange, message, nextToken)
	case strconv.ErrSyntax:
		panic(fmt.Sprintf("Lexer allowed unparsable float literal: %s. "+
			"Kind = %s. error=%s.", nextToken.Text, nextToken.Kind, err))
	}
	return 0, false
}

///////////////// Parsing Helper Functions ////////

func (p *Parser) match(expectedKind lexer.TokenKind) bool {
	if !p.OK() {
		return false
	}
	message := fmt.Sprintf("Expecting %s.", expectedKind)
	nextToken := p.peekNextToken(message)
	if !p.OK() {
		return false
	}
	if nextToken.Kind != expectedKind {
		expected := fmt.Sprintf("%s", expectedKind)
		p.unexpectedTokenError(nextToken, expected)
		return false
	}
	p.consumeNextToken()
	return true
}

func (p *Parser) tryMatch(expectedKind lexer.TokenKind) bool {
	if p.checkEOF() {
		return false
	}
	if !p.OK() {
		return false
	}
	nextToken := p.peekNextToken("")
	if nextToken.Kind != expectedKind {
		return false
	}
	p.consumeNextToken()
	return true
}

func (p *Parser) matchSemicolonToken(previousToken lexer.Token) bool {
	if !p.OK() {
		return false
	}
	if p.match(lexer.Semi) {
		return true
	}
	message := fmt.Sprintf("Missing semicolon after %s.", previousToken)
	p.parseErrorT(ParserErrorCodeUnexpectedToken, message, previousToken)
	return false
}

func (p *Parser) matchSemicolon() bool {
	return p.matchSemicolonToken(p.lastConsumed)
}

func (p *Parser) readText(kind lexer.TokenKind) (text string) {
	if !p.OK() {
		return
	}

	if !p.match(kind) {
		return
	}
	return p.lastConsumed.Text
}

func (p *Parser) readStringLiteral() (literal string) {
	if !p.OK() {
		return
	}

	if !p.match(lexer.StringLiteral) {
		return
	}

	return lexer.StringLiteralTokenToText(p.lastConsumed)
}

func (p *Parser) readName() (name string) {
	if !p.OK() {
		return
	}
	name = p.readText(lexer.Name)
	return
}

// Returns (-1, nil) if there was no specified ordinal.
func (p *Parser) readOrdinal() (ordinalValue int64, err error) {
	ordinalValue = -1
	if !p.OK() {
		return
	}

	if p.tryMatch(lexer.Ordinal) {
		intTextToParse := p.lastConsumed.Text[1:]
		ordinalValue, err = strconv.ParseInt(intTextToParse, 10, 64)
		if err != nil || ordinalValue < 0 || ordinalValue >= math.MaxUint32 {
			err = fmt.Errorf("Invalid ordinal string following '@': %q. Ordinals must be decimal integers between 0 and %d.",
				intTextToParse, math.MaxUint32-1)
			return
		}
	}
	return
}

func (p *Parser) DeclData(name string, nameToken lexer.Token, attributes *mojom.Attributes) mojom.DeclarationData {
	return mojom.DeclData(name, p.mojomFile, nameToken, attributes)
}

func (p *Parser) DeclDataWithOrdinal(name string, nameToken lexer.Token, attributes *mojom.Attributes, declaredOrdinal int64) mojom.DeclarationData {
	return mojom.DeclDataWithOrdinal(name, p.mojomFile, nameToken, attributes, declaredOrdinal)
}

////////////////// Scope Stack /////////////////////
///
func (p *Parser) pushScope(scope *mojom.Scope) {
	if p.currentScope == nil {
		p.currentScope = scope
	} else {
		if scope.Parent() != p.currentScope {
			panic("Can only push child of current scope.")
		}
		p.currentScope = scope
	}
}

func (p *Parser) popScope() {
	if p.currentScope != nil {
		p.currentScope = p.currentScope.Parent()
	}
}

/////////// Utility functions

func (p *Parser) invalidOrdinalError(objectType, objectName string, nameToken lexer.Token, err error) {
	message := fmt.Sprintf("%s %q: %s", objectType, objectName, err.Error())
	p.parseErrorT(ParserErrorCodeBadOrdinal, message, nameToken)
}

// unexpectedTokenError() sets the parser's current error to a ParseError
// with error code |ParserErrorCodeUnexpectedToken| and an error message
// of the form:
//
//    Unexpected '}'. Expecting a semicolon.
//
// |expected| should be a noun-phrase such as "a semicolon".
func (p *Parser) unexpectedTokenError(token lexer.Token, expected string) {
	var message string
	switch token.Kind {
	case lexer.ErrorUnterminatedStringLiteral, lexer.ErrorUnterminatedComment:
		message = fmt.Sprintf("%s", token)
	default:
		message = fmt.Sprintf("Unexpected %s. Expecting %s.", token, expected)
	}
	p.parseErrorT(ParserErrorCodeUnexpectedToken, message, token)
}
