func (x *hclLex) lexId(yylval *hclSymType) int {
	var b bytes.Buffer
	first := true
	for {
		c := x.next()
		if c == lexEOF {
			break
		}
		if !unicode.IsDigit(c) && !unicode.IsLetter(c) &&
			c != '_' && c != '-' && c != '.' {
			x.backup()
			if first {
				x.createErr("Invalid identifier")
				return lexEOF
			}
			break
		}
		first = false
		if _, err := b.WriteRune(c); err != nil {
			return lexEOF
		}
	}
	yylval.str = b.String()
	switch yylval.str {
	case "true":
		yylval.b = true
		return BOOL
	case "false":
		yylval.b = false
		return BOOL
	}
	return IDENTIFIER
}
lexId lexes an identifier
package hcl
import (
	"bytes"
	"fmt"
	"strconv"
	"unicode"
	"unicode/utf8"
)
const lexEOF = 0
type hclLex struct {
	Input string
	lastNumber        bool
	pos               int
	width             int
	col, line         int
	lastCol, lastLine int
	err               error
}
func (x *hclLex) Lex(yylval *hclSymType) int {
	for {
		c := x.next()
		if c == lexEOF {
			return lexEOF
		}
		if unicode.IsSpace(c) {
			x.lastNumber = false
			continue
		}
		switch c {
		case '#':
			fallthrough
		case '/':
			if !x.consumeComment(c) {
				return lexEOF
			}
			continue
		}
		if c >= '0' && c <= '9' {
			x.lastNumber = true
			x.backup()
			return x.lexNumber(yylval)
		}
		if x.lastNumber {
			switch c {
			case 'e':
				fallthrough
			case 'E':
				switch x.next() {
				case '+':
					return EPLUS
				case '-':
					return EMINUS
				default:
					x.backup()
					return EPLUS
				}
			}
		}
		x.lastNumber = false
		switch c {
		case '.':
			return PERIOD
		case '-':
			return MINUS
		case ',':
			return x.lexComma()
		case '=':
			return EQUAL
		case '[':
			return LEFTBRACKET
		case ']':
			return RIGHTBRACKET
		case '{':
			return LEFTBRACE
		case '}':
			return RIGHTBRACE
		case '"':
			return x.lexString(yylval)
		case '<':
			return x.lexHeredoc(yylval)
		default:
			x.backup()
			return x.lexId(yylval)
		}
	}
}
func (x *hclLex) consumeComment(c rune) bool {
	single := c == '#'
	if !single {
		c = x.next()
		if c != '/' && c != '*' {
			x.backup()
			x.createErr(fmt.Sprintf("comment expected, got '%c'", c))
			return false
		}
		single = c == '/'
	}
	nested := 1
	for {
		c = x.next()
		if c == lexEOF {
			x.backup()
			return true
		}
		if single {
			if c == '\n' {
				return true
			}
			continue
		}
		switch c {
		case '/':
			c = x.next()
			if c == '*' {
				nested++
			} else {
				x.backup()
			}
		case '*':
			c = x.next()
			if c == '/' {
				nested--
			} else {
				x.backup()
			}
		default:
		}
		if nested == 0 {
			return true
		}
	}
}
func (x *hclLex) lexComma() int {
	for {
		c := x.peek()
		if unicode.IsSpace(c) {
			x.next()
			continue
		}
		if c == ']' {
			return COMMAEND
		}
		break
	}
	return COMMA
}