go-rfc8259/number/parse.go

111 lines
2.4 KiB
Go
Raw Normal View History

2023-11-06 12:29:42 +00:00
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
}