Example #1
0
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
	}
}
Example #2
0
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
}