// lexCommentStart begins the lexing of a comment. It will emit
// itemCommentStart and consume no characters, passing control to lexComment.
359282
func lexCommentStart(lx *lexer) stateFn {
	lx.ignore()
	lx.emit(itemCommentStart)
	return lexComment
}
999956
func (l *Lexer) consumeHTMLLikeCommentToken() bool {
	c := l.r.Peek(0)
	if c == '<' && l.r.Peek(1) == '!' && l.r.Peek(2) == '-' && l.r.Peek(3) == '-' {
		// opening HTML-style single line comment
		l.r.Move(4)
		l.consumeSingleLineComment()
		return true
	} else if l.emptyLine && c == '-' && l.r.Peek(1) == '-' && l.r.Peek(2) == '>' {
		// closing HTML-style single line comment
		// (only if current line didn't contain any meaningful tokens)
		l.r.Move(3)
		l.consumeSingleLineComment()
		return true
	}
	return false
}
108135
func lex(name, input string) *lexer {
	l := &lexer{
		name:  name,
		input: input,
		items: make(chan item),
		state: lexText,
	}
	go l.run()
	return l
}
881432
func lexIncludeStart(lx *lexer) stateFn {
	r := lx.next()
	if isWhitespace(r) {
		return lexSkip(lx, lexIncludeStart)
	}
	lx.backup()
	return lexInclude
}
367016
func (l *Lexer) Lex(lval *yySymType) int {
	tok, lit, pos, err := l.s.Scan()
	if err != nil {
		l.e = &Error{Message: err.Error(), Pos: pos, Fatal: true}
	}
	lval.tok = ast.Token{Tok: tok, Lit: lit}
	lval.tok.SetPosition(pos)
	l.lit = lit
	l.pos = pos
	return tok
}
964518
func DocComments(path string) (docs map[string]map[string][]*ast.Comment, err error) {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, path, nil, parser.ParseComments)
	if err != nil {
		return nil, err
	}

	docs = make(map[string]map[string][]*ast.Comment)
	for _, p := range pkgs {
		for _, f := range p.Files {
			for _, n := range f.Decls {
				fn, ok := n.(*ast.FuncDecl)
				if !ok || fn.Doc == nil {
					continue
				}

				var typ string
				if fn.Recv != nil && len(fn.Recv.List) > 0 {
					id, ok := fn.Recv.List[0].Type.(*ast.Ident)
					if ok {
						typ = id.Name
					}
				}
				doc, ok := docs[typ]
				if !ok {
					doc = make(map[string][]*ast.Comment)
					docs[typ] = doc
				}
				doc[fn.Name.String()] = fn.Doc.List
			}
		}
	}
	return docs, nil
}
753705
func lexText(l *lexer) stateFn {
	for {
		if i := strings.IndexByte(l.input[l.pos:], l.leftDelim[0]); i == -1 {
			l.pos = Pos(len(l.input))
			break
		} else {
			l.pos += Pos(i)
			if strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
				if l.pos > l.start {
					l.emit(itemText)
				}
				return lexLeftDelim
			}
			if strings.HasPrefix(l.input[l.pos:], leftComment) {
				if l.pos > l.start {
					l.emit(itemText)
				}
				return lexComment
			}
		}
		if l.next() == eof {
			break
		}
	}
	// Correctly reached EOF.
	if l.pos > l.start {
		l.emit(itemText)
	}
	l.emit(itemEOF)
	return nil
}
168548
func (l *lexer) lexSymbol() error {
	r := l.next()

	// Single line C++ style comment
	if r == '#' || (r == '/' && l.peek() == '/') {
		comment, blanks, indent := l.lexUntilNewline()
		var k ast.FodderKind
		if l.freshLine {
			k = ast.FodderParagraph
		} else {
			k = ast.FodderLineEnd
		}
		l.addFodder(k, blanks, indent, []string{string(r) + comment})
		return nil
	}

	// C style comment (could be interstitial or paragraph comment)
	if r == '/' && l.peek() == '*' {
		margin := l.pos.byteNo - l.pos.lineStart
		commentStartLoc := l.tokenStartLoc

		r := l.next() // consume the initial '*'
		for r = l.next(); r != '*' || l.peek() != '/'; r = l.next() {
			if r == lexEOF {
				return l.makeStaticErrorPoint(
					"Multi-line comment has no terminating */",
					commentStartLoc)
			}
		}

		l.next() // Consume trailing '/'
		// Includes the "/*" and "*/".
		comment := l.input[l.tokenStart:l.pos.byteNo]

		newLinesAfter, indentAfter := l.lexWhitespace()
		if !strings.ContainsRune(comment, '\n') {
			l.addFodder(ast.FodderInterstitial, 0, 0, []string{comment})
			if newLinesAfter > 0 {
				l.addFodder(ast.FodderLineEnd, newLinesAfter-1, indentAfter, []string{})
			}
		} else {
			lines := lineSplit(comment, margin)
			if lines[0][0] != '/' {
				panic(fmt.Sprintf("Invalid parsing of C style comment %v", lines))
			}
			// Little hack to support FodderParagraphs with * down the LHS:
			// Add a space to lines that start with a '*'
			allStar := true
			for _, l := range lines {
				if len(l) == 0 || l[0] != '*' {
					allStar = false
				}
			}
			if allStar {
				for _, l := range lines {
					if l[0] == '*' {
						l = " " + l
					}
				}
			}
			if newLinesAfter == 0 {
				// Ensure a line end after the paragraph.
				newLinesAfter = 1
				indentAfter = 0
			}
			l.addFodder(ast.FodderParagraph, newLinesAfter-1, indentAfter, lines)
		}
		return nil
	}

	if r == '|' && strings.HasPrefix(l.input[l.pos.byteNo:], "||") {
		commentStartLoc := l.tokenStartLoc
		l.acceptN(2) // Skip "||"
		var cb bytes.Buffer

		// Skip whitespace
		for r = l.next(); r == ' ' || r == '\t' || r == '\r'; r = l.next() {
		}

		// Skip \n
		if r != '\n' {
			return l.makeStaticErrorPoint("Text block requires new line after |||.",
				commentStartLoc)
		}

		// Process leading blank lines before calculating stringBlockIndent
		for r = l.next(); r == '\n'; r = l.next() {
			cb.WriteRune(r)
		}
		l.backup()
		numWhiteSpace := checkWhitespace(l.input[l.pos.byteNo:], l.input[l.pos.byteNo:])
		stringBlockIndent := l.input[l.pos.byteNo : l.pos.byteNo+numWhiteSpace]
		if numWhiteSpace == 0 {
			return l.makeStaticErrorPoint("Text block's first line must start with whitespace",
				commentStartLoc)
		}

		for {
			if numWhiteSpace <= 0 {
				panic("Unexpected value for numWhiteSpace")
			}
			l.acceptN(numWhiteSpace)
			for r = l.next(); r != '\n'; r = l.next() {
				if r == lexEOF {
					return l.makeStaticErrorPoint("Unexpected EOF", commentStartLoc)
				}
				cb.WriteRune(r)
			}
			cb.WriteRune('\n')

			// Skip any blank lines
			for r = l.next(); r == '\n'; r = l.next() {
				cb.WriteRune(r)
			}
			l.backup()

			// Look at the next line
			numWhiteSpace = checkWhitespace(stringBlockIndent, l.input[l.pos.byteNo:])
			if numWhiteSpace == 0 {
				// End of the text block
				var stringBlockTermIndent string
				for r = l.next(); r == ' ' || r == '\t'; r = l.next() {
					stringBlockTermIndent += string(r)
				}
				l.backup()
				if !strings.HasPrefix(l.input[l.pos.byteNo:], "|||") {
					return l.makeStaticErrorPoint("Text block not terminated with |||", commentStartLoc)
				}
				l.acceptN(3) // Skip '|||'
				l.emitFullToken(tokenStringBlock, cb.String(),
					stringBlockIndent, stringBlockTermIndent)
				l.resetTokenStart()
				return nil
			}
		}
	}

	// Assume any string of symbols is a single operator.
	for r = l.next(); isSymbol(r); r = l.next() {
		// Not allowed // in operators
		if r == '/' && strings.HasPrefix(l.input[l.pos.byteNo:], "/") {
			break
		}
		// Not allowed /* in operators
		if r == '/' && strings.HasPrefix(l.input[l.pos.byteNo:], "*") {
			break
		}
		// Not allowed ||| in operators
		if r == '|' && strings.HasPrefix(l.input[l.pos.byteNo:], "||") {
			break
		}
	}

	l.backup()

	// Operators are not allowed to end with + - ~ ! unless they are one rune long.
	// So, wind it back if we need to, but stop at the first rune.
	// This relies on the hack that all operator symbols are ASCII and thus there is
	// no need to treat this substring as general UTF-8.
	for r = rune(l.input[l.pos.byteNo-1]); l.pos.byteNo > l.tokenStart+1; l.pos.byteNo-- {
		switch r {
		case '+', '-', '~', '!', '$':
			continue
		}
		break
	}

	if l.input[l.tokenStart:l.pos.byteNo] == "$" {
		l.emitToken(tokenDollar)
	} else {
		l.emitToken(tokenOperator)
	}
	return nil
}
1195729
func (l *lexer) emit(t itemType) {
	if l.pos > ast.Pos(len(l.input)) {
		l.pos = ast.Pos(len(l.input))
	}
	l.lastEmit = item{t, l.pos, l.input[l.start:l.pos]}
	l.items <- l.lastEmit
	l.start = l.pos
}
60201
func lexOptions(l *lexer) stateFn {
	for {
		n := l.next()
		if any(n, spaces) {
			l.acceptRun(spaces)
			l.emit(itemSpace)
		} else if n == ':' {
			l.emit(itemColon)
			return lexCommand
		} else if n == '+' {
			l.acceptWord()
			l.emit(itemBareString)
		} else {
			l.errorf("invalid command option")
			return nil
		}
	}
}
1183868
func maybeEmitText(l *lexer, backup int) {
	if l.pos-ast.Pos(backup) > l.start {
		l.pos -= ast.Pos(backup)
		if allSpaceWithNewline(l.input[l.start:l.pos]) {
			l.ignore()
		} else {
			l.emit(itemText)
		}
		l.pos += ast.Pos(backup)
	}
}
335965
func (f *file) containsComments(start, end token.Pos) bool {
	for _, cgroup := range f.f.Comments {
		comments := cgroup.List
		if comments[0].Slash >= end {
			// All comments starting with this group are after end pos.
			return false
		}
		if comments[len(comments)-1].Slash < start {
			// Comments group ends before start pos.
			continue
		}
		for _, c := range comments {
			if start <= c.Slash && c.Slash < end && !strings.HasPrefix(c.Text, "// MATCH ") {
				return true
			}
		}
	}
	return false
}
546357
func (z *Lexer) Lexeme() []byte {
	return z.buf[z.start:z.pos]
}
178577
func lexComment(l *Lexer) lexFunc {
	if str := l.findRegexp(l.closeComment); str != "" {
		l.pos += len(str)
		l.emit(TokenComment)

		return lexContent
	}

	if r := l.next(); r == eof {
		return l.errorf("Unclosed comment")
	}

	return lexComment
}
707049
func lex(name string, input []byte) *lexer {
	l := &lexer{
		name:  name,
		input: string(input),
		items: make(chan item),
		line:  1,
	}
	go l.run()
	return l
}
87514
func lexMapEnd(lx *lexer) stateFn {
	lx.ignore()
	lx.emit(itemMapEnd)
	return lx.pop()
}
962572
func lexExpr(name, input string) *lexer {
	l := &lexer{
		name:  name,
		input: input,
		items: make(chan item),
		state: lexInsideTag,
	}
	go l.run()
	return l
}