|
@@ -65,9 +65,22 @@ var (
|
|
errInvalidCommand = errors.New("command must be one of \"from\", \"license\", \"template\", \"system\", \"adapter\", \"parameter\", or \"message\"")
|
|
errInvalidCommand = errors.New("command must be one of \"from\", \"license\", \"template\", \"system\", \"adapter\", \"parameter\", or \"message\"")
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+type ParserError struct {
|
|
|
|
+ LineNumber int
|
|
|
|
+ Msg string
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (e *ParserError) Error() string {
|
|
|
|
+ if e.LineNumber > 0 {
|
|
|
|
+ return fmt.Sprintf("(line %d): %s", e.LineNumber, e.Msg)
|
|
|
|
+ }
|
|
|
|
+ return e.Msg
|
|
|
|
+}
|
|
|
|
+
|
|
func ParseFile(r io.Reader) (*File, error) {
|
|
func ParseFile(r io.Reader) (*File, error) {
|
|
var cmd Command
|
|
var cmd Command
|
|
var curr state
|
|
var curr state
|
|
|
|
+ var currLine int = 1
|
|
var b bytes.Buffer
|
|
var b bytes.Buffer
|
|
var role string
|
|
var role string
|
|
|
|
|
|
@@ -84,11 +97,18 @@ func ParseFile(r io.Reader) (*File, error) {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if isNewline(r) {
|
|
|
|
+ currLine++
|
|
|
|
+ }
|
|
|
|
+
|
|
next, r, err := parseRuneForState(r, curr)
|
|
next, r, err := parseRuneForState(r, curr)
|
|
if errors.Is(err, io.ErrUnexpectedEOF) {
|
|
if errors.Is(err, io.ErrUnexpectedEOF) {
|
|
return nil, fmt.Errorf("%w: %s", err, b.String())
|
|
return nil, fmt.Errorf("%w: %s", err, b.String())
|
|
} else if err != nil {
|
|
} else if err != nil {
|
|
- return nil, err
|
|
|
|
|
|
+ return nil, &ParserError{
|
|
|
|
+ LineNumber: currLine,
|
|
|
|
+ Msg: err.Error(),
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// process the state transition, some transitions need to be intercepted and redirected
|
|
// process the state transition, some transitions need to be intercepted and redirected
|
|
@@ -96,7 +116,10 @@ func ParseFile(r io.Reader) (*File, error) {
|
|
switch curr {
|
|
switch curr {
|
|
case stateName:
|
|
case stateName:
|
|
if !isValidCommand(b.String()) {
|
|
if !isValidCommand(b.String()) {
|
|
- return nil, errInvalidCommand
|
|
|
|
|
|
+ return nil, &ParserError{
|
|
|
|
+ LineNumber: currLine,
|
|
|
|
+ Msg: errInvalidCommand.Error(),
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// next state sometimes depends on the current buffer value
|
|
// next state sometimes depends on the current buffer value
|
|
@@ -117,7 +140,10 @@ func ParseFile(r io.Reader) (*File, error) {
|
|
cmd.Name = b.String()
|
|
cmd.Name = b.String()
|
|
case stateMessage:
|
|
case stateMessage:
|
|
if !isValidMessageRole(b.String()) {
|
|
if !isValidMessageRole(b.String()) {
|
|
- return nil, errInvalidMessageRole
|
|
|
|
|
|
+ return nil, &ParserError{
|
|
|
|
+ LineNumber: currLine,
|
|
|
|
+ Msg: errInvalidMessageRole.Error(),
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
role = b.String()
|
|
role = b.String()
|