func symbolDispatcher(table map[string]parser.Parser) parser.Parser { ws := parser.Whitespace() return func(st *parser.State) (parser.Output, bool, error) { next, err := st.Input.Next() if err != nil || !(next >= 'a' && next <= 'z') { return nil, false, err } st.Input.Pop(1) runes := make([]rune, 1, 8) runes[0] = next for { next, err := st.Input.Next() if err == io.EOF || next == ' ' { break } else if err != nil { return nil, false, err } st.Input.Pop(1) runes = append(runes, next) } sym := string(runes) par := table[sym] if par == nil { return nil, false, nil } _, ok, err := ws(st) if !ok || err != nil { return nil, false, err } out, ok, err := par(st) return symbolValue{sym, out}, ok, err } }
func buildParser() parser.Parser { constantValue := parser.Lexeme(parser.Any(quotedString(), integer(), float())) namespaceDef := parser.Collect( parser.Identifier(), parser.Identifier()) includeDef := parser.Collect( parser.Lexeme(quotedString())) var typeDef func(st *parser.State) (parser.Output, bool, error) recurseTypeDef := func(st *parser.State) (parser.Output, bool, error) { return typeDef(st) } typeDef = parser.Any( parser.Identifier(), parser.Collect(parser.Symbol("list"), parser.Symbol("<"), recurseTypeDef, parser.Symbol(">")), parser.Collect(parser.Symbol("set"), parser.Symbol("<"), recurseTypeDef, parser.Symbol(">")), parser.Collect(parser.Symbol("map"), parser.Symbol("<"), recurseTypeDef, parser.Symbol(","), recurseTypeDef, parser.Symbol(">")), ) typedefDef := parser.Collect(typeDef, parser.Identifier()) constDef := parser.Collect( typeDef, parser.Identifier(), parser.Symbol("="), constantValue, parser.Any( parser.Symbol(","), parser.Symbol(";"), parser.Symbol(""), ), ) enumItemDef := parser.Collect( parser.Identifier(), parser.Any( parser.All(parser.Symbol("="), parser.Lexeme(integer())), nilParser(), ), parser.Any(parser.Symbol(","), parser.Symbol(";"), parser.Symbol("")), ) enumDef := parser.Collect( parser.Identifier(), parser.Symbol("{"), parser.Many(enumItemDef), parser.Symbol("}"), ) structFieldDef := parser.Collect( parser.Any( parser.Collect(parser.Lexeme(integer()), parser.Symbol(":")), nilParser(), ), parser.Any(parser.Symbol("required"), parser.Symbol("optional"), parser.Symbol("")), typeDef, parser.Identifier(), // Default parser.Any( parser.All(parser.Symbol("="), parser.Lexeme(parser.Any( parser.Identifier(), quotedString(), parser.Try(float()), integer()))), nilParser(), ), parser.Skip(parser.Any(parser.Symbol(","), parser.Symbol(";"), parser.Symbol(""))), ) structDef := parser.Collect( parser.Identifier(), parser.Symbol("{"), parser.Many(structFieldDef), parser.Symbol("}"), ) serviceMethodDef := parser.Collect( // // parser.Comments(), // parser.Whitespace(), parser.Any(parser.Symbol("oneway"), parser.Symbol("")), typeDef, parser.Identifier(), parser.Symbol("("), parser.Many(structFieldDef), parser.Symbol(")"), // Exceptions parser.Any( parser.Collect( parser.Symbol("throws"), parser.Symbol("("), parser.Many(structFieldDef), parser.Symbol(")"), ), nilParser(), ), parser.Any(parser.Symbol(","), parser.Symbol(";"), parser.Symbol("")), ) // <identifier> [extends <identifier>] { <*serviceMethodDef> } serviceDef := parser.Collect( parser.Identifier(), parser.Any( parser.Collect(parser.Symbol("extends"), parser.Identifier()), nilParser(), ), parser.Symbol("{"), parser.Many(serviceMethodDef), parser.Symbol("}"), ) thriftSpec := parser.All(parser.Whitespace(), parser.Many( symbolDispatcher(map[string]parser.Parser{ "namespace": namespaceDef, "typedef": typedefDef, "const": constDef, "include": includeDef, "enum": enumDef, "exception": structDef, "struct": structDef, "service": serviceDef, }), )) return thriftSpec }