go-rfc8259/number/parse.go

111 lines
2.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package rfc8259number
import (
"io"
"sourcecode.social/reiver/go-rfc8259/errors"
"sourcecode.social/reiver/go-rfc8259/exponentnumber"
"sourcecode.social/reiver/go-rfc8259/fractionalnumber"
"sourcecode.social/reiver/go-rfc8259/naturalnumber"
)
// Parse tries to parse a JSON number literal.
// If it succeeds, then it return nil, and sets dst to the parsed value.
// If it failed, it returns an error.
//
// Example usage:
//
// var rs io.RuneScaner
//
// // ...
//
// var value rfc8259number.Number
// err := rfc8259number.Parse(rs, &value)
//
// if nil != err {
// return err
// }
//
// fmt.Printf("value = %#v\n", value)
func Parse(runescanner io.RuneScanner, dst *Number) error {
if nil == runescanner {
return rfc8259errors.ErrNilRuneScanner
}
if nil == dst {
return rfc8259errors.ErrNilDestination
}
var natPart rfc8259naturalnumber.NaturalNumber // [ minus ] int
var fracPart rfc8259fractionalnumber.FractionalNumber // [ frac ]
var expPart rfc8259exponentnumber.ExponentNumber // [ exp ]
// [ minus ] int
{
if err := rfc8259naturalnumber.Parse(runescanner, &natPart); nil != err {
return err
}
if rfc8259naturalnumber.Nothing() == natPart {
return rfc8259errors.ErrInternalError("expected the result of a natural-number, but it is actually nothing")
}
}
// [ frac ]
{
var r rune
{
var err error
r, _, err = runescanner.ReadRune()
if nil != err {
if io.EOF == err {
natPart.WhenSomething(func(value string){
*dst = Something(value)
})
return nil
}
return rfc8259errors.ErrProblemReadingRune(err)
}
if err := runescanner.UnreadRune(); nil != err {
return rfc8259errors.ErrProblemUnreadingRune(err, r)
}
}
if '.' == r {
if err := rfc8259fractionalnumber.Parse(runescanner, &fracPart); nil != err {
return err
}
}
}
// [ exp ]
{
var r rune
{
var err error
r, _, err = runescanner.ReadRune()
if nil != err {
if io.EOF == err {
*dst = Something(natPart.GetElse("") + fracPart.GetElse(""))
return nil
}
return rfc8259errors.ErrProblemReadingRune(err)
}
if err := runescanner.UnreadRune(); nil != err {
return rfc8259errors.ErrProblemUnreadingRune(err, r)
}
}
if 'E' == r || 'e' == r {
if err := rfc8259exponentnumber.Parse(runescanner, &expPart); nil != err {
return err
}
}
}
*dst = Something(natPart.GetElse("") + fracPart.GetElse("") + expPart.GetElse(""))
return nil
}