func LexForExpr(l *lex.Lexer) lex.StateFn { if int(l.Pos) >= len(l.Input) { l.Emit(lex.ItemEOF) return nil } if strings.HasPrefix(l.Input[l.Pos:], "in") { l.Pos += lex.Pos(2) l.Emit(ItemIn) return InsideAction } // any list of space separated identifiers switch r := l.Next(); { case lex.IsSpace(r): for lex.IsSpace(l.Peek()) { l.Next() } l.Emit(ItemSpace) return LexForExpr case unicode.IsLetter(r): return LoopIdentifier default: return l.Errorf("Unexpected Character '%s'", string(r)) } }
func Number(l *lex.Lexer) lex.StateFn { if !l.ScanNumber() { return l.Errorf("bad number syntax: %q", l.Input[l.Start:l.Pos]) } l.Emit(ItemNumber) return InsideAction }
func InsideAction(l *lex.Lexer) lex.StateFn { if l.Name == "LexTextNode" && strings.HasPrefix(l.Input[l.Pos:], rightDelim) { if l.IntState[ActionParenDepth] > 0 { return l.Errorf("unmatched parentheses") } return RightDelim } switch r := l.Next(); { case (r == lex.EOF || lex.IsEndOfLine(r)): if l.Name == "LexIfExpr" { return LexIfExpr } if l.Name == "LexForExpr" { return LexForExpr } // if reach eof throw while still in action throw error return l.Errorf("unclosed action") case lex.IsSpace(r): return Space case unicode.IsLetter(r): //variable and function must begin with a letter return Identifier case r == '!': if unicode.IsLetter(l.Peek()) { return Identifier } return l.Errorf("invalid character in builtin") case r == '#' || r == '+': if unicode.IsLetter(l.Peek()) { return EspraURI } return l.Errorf("invalid character in URI") case r == '-' || unicode.IsDigit(r): l.Backup() return Number case r == '\'' || r == '"': l.Emit(ItemOpenQuote) return String case r == '(': l.IntState[ActionParenDepth] += 1 l.Emit(ItemLeftParen) case r == ')': l.IntState[ActionParenDepth] -= 1 l.Emit(ItemRightParen) case r == '|': l.Emit(ItemPipe) default: return l.Errorf("Unexpected Character '%s'", string(r)) } return InsideAction }
// Quote scans a quoted string. func String(l *lex.Lexer) lex.StateFn { Loop: for { switch l.Next() { case '\\': // ??? if r := l.Next(); r != lex.EOF && r != '\n' { break } fallthrough case lex.EOF, '\n': return l.Errorf("unterminated quoted string") case '"', '\'': l.Backup() break Loop } } l.Emit(ItemString) l.Next() l.Emit(ItemCloseQuote) return InsideAction }