Пример #1
0
func init() {
	end := hammer.Ch('e')
	colon := hammer.Ch(':')
	neg := hammer.Ch('-')

	digits := hammer.Many1(hammer.ChRange('0', '9'))

	uint_10 := hammer.Action(digits, func(token ast.Token) (ast.Token, bool) {
		numstr := charSequenceString(token.Value.([]ast.Token))

		num, err := strconv.ParseUint(numstr, 10, 64)
		if err != nil {
			return token, false
		}

		token.Value = num
		return token, true
	})

	int_10 := hammer.Action(hammer.Sequence(hammer.Optional(neg), digits), func(token ast.Token) (ast.Token, bool) {
		tokens := token.Value.([]ast.Token)
		neg, digits := tokens[0], tokens[1]
		numstr := charSequenceString(digits.Value.([]ast.Token))

		num, err := strconv.ParseInt(numstr, 10, 64)
		if err != nil {
			return token, false
		}

		if neg.Value != ast.None {
			num *= -1
		}

		token.Value = num
		return token, true
	})

	b_string := hammer.LengthValue(hammer.Left(uint_10, colon), hammer.Uint8())
	b_int := hammer.Sequence(hammer.Ch('i'), int_10, end)
	b_list := hammer.Indirect()
	b_dict := hammer.Indirect()

	anyType := hammer.Choice(b_int, b_string, b_list, b_dict)

	hammer.BindIndirect(b_list, hammer.Sequence(
		hammer.Ch('l'),
		hammer.Many(anyType),
		end,
	))
	hammer.BindIndirect(b_dict, hammer.Sequence(
		hammer.Ch('d'),
		hammer.Many(hammer.Sequence(b_string, anyType)),
		end,
	))

	bencode = anyType
}
Пример #2
0
func jsonParser_init() hammer.Parser {
	// string
	jsonString := hammer.Sequence(
		hammer.Ch('"'),
		hammer.Many1(
			hammer.Choice(
				hammer.ChRange('\x20', '\x21'), // skip "
				hammer.ChRange('\x23', '\x2E'), // skip /
				hammer.ChRange('\x30', '\x5B'), // skip \
				hammer.ChRange('\x5D', '\x7E'), // skip DEL
				hammer.Sequence(hammer.Ch('\\'), hammer.Ch('"')),
				hammer.Sequence(hammer.Ch('\\'), hammer.Ch('\\')),
				hammer.Sequence(hammer.Ch('\\'), hammer.Ch('/')),
				hammer.Sequence(hammer.Ch('\\'), hammer.Ch('b')),
				hammer.Sequence(hammer.Ch('\\'), hammer.Ch('f')),
				hammer.Sequence(hammer.Ch('\\'), hammer.Ch('n')),
				hammer.Sequence(hammer.Ch('\\'), hammer.Ch('r')),
				hammer.Sequence(hammer.Ch('\\'), hammer.Ch('t')),
				hammer.Sequence(hammer.Ch('\\'), hammer.Ch('u')),
			),
		),
		hammer.Ch('"'),
	)

	// number
	jsonNumber := hammer.Sequence(
		hammer.Optional(hammer.Ch('-')),
		hammer.Choice(
			hammer.Ch('0'),
			hammer.Sequence(
				hammer.ChRange('1', '9'),
				hammer.Many1(hammer.ChRange('0', '9')),
			),
		),
		hammer.Optional(hammer.Sequence(
			hammer.Ch('.'),
			hammer.Many1(hammer.ChRange(0, 9)),
		)),
		hammer.Optional(hammer.Sequence(
			hammer.Choice(hammer.Ch('e'), hammer.Ch('E')),
			hammer.Optional(hammer.Choice(hammer.Ch('+'), hammer.Ch('-'))),
			hammer.Many1(hammer.ChRange(0, 9)),
		)),
	)

	// indirects for use in value
	jsonArray := hammer.Indirect()
	jsonObject := hammer.Indirect()

	// value
	jsonValue := hammer.Choice(
		jsonString,
		jsonNumber,
		jsonObject,
		jsonArray,
		hammer.Token([]byte("true")),
		hammer.Token([]byte("false")),
		hammer.Token([]byte("null")),
	)

	// array
	hammer.BindIndirect(jsonArray,
		hammer.Sequence(
			hammer.Ch('['),
			hammer.SepBy1(jsonValue, hammer.Ch(',')),
			hammer.Ch(']'),
		),
	)

	// object
	hammer.BindIndirect(jsonObject,
		hammer.Sequence(
			hammer.Ch('{'),
			jsonString,
			hammer.Ch(':'),
			jsonValue,
			hammer.Ch('}'),
		),
	)

	return jsonObject
}