Add more functionality to the ErLang parser (#2390)

* ERLang parser support for empty lists
* ERLang add support for single quote strings
* ERLang parser support for comments
---------
Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>
This commit is contained in:
Laurent Goderre
2023-12-22 09:45:20 -05:00
committed by GitHub
parent 63e7a004cb
commit 3a6b6562d1
2 changed files with 88 additions and 1 deletions
+46 -1
View File
@@ -2,6 +2,7 @@ package erlang
import (
"bytes"
"errors"
"fmt"
"io"
"strings"
@@ -12,6 +13,8 @@ type erlangNode struct {
value interface{}
}
var errSkipComments = errors.New("")
func (e erlangNode) Slice() []erlangNode {
out, ok := e.value.([]erlangNode)
if ok {
@@ -56,6 +59,10 @@ func parseErlang(reader io.Reader) (erlangNode, error) {
i := 0
for i < len(data) {
item, err := parseErlangBlock(data, &i)
if err == errSkipComments {
skipWhitespace(data, &i)
continue
}
if err != nil {
return node(nil), fmt.Errorf("%w\n%s", err, printError(data, i))
}
@@ -141,11 +148,26 @@ func parseErlangNode(data []byte, i *int) (erlangNode, error) {
c := data[*i]
switch c {
case '[', '{':
offset := *i + 1
skipWhitespace(data, &offset)
c2 := data[offset]
// Add support for empty lists
if (c == '[' && c2 == ']') || (c == '{' && c2 == '}') {
*i = offset + 1
return node(nil), nil
}
return parseErlangList(data, i)
case '"':
fallthrough
case '\'':
return parseErlangString(data, i)
case '<':
return parseErlangAngleString(data, i)
case '%':
parseErlangComment(data, i)
return node(nil), errSkipComments
}
if isLiteral(c) {
@@ -205,7 +227,7 @@ func parseErlangString(data []byte, i *int) (erlangNode, error) {
buf.WriteByte(c)
*i++
}
return node(buf.String()), nil
return node(nil), fmt.Errorf("unterminated string at %d", *i)
}
func parseErlangList(data []byte, i *int) (erlangNode, error) {
@@ -216,6 +238,10 @@ func parseErlangList(data []byte, i *int) (erlangNode, error) {
for *i < len(data) {
item, err := parseErlangNode(data, i)
if err != nil {
if err == errSkipComments {
skipWhitespace(data, i)
continue
}
return node(nil), err
}
out.value = append(out.value.([]erlangNode), item)
@@ -225,6 +251,9 @@ func parseErlangList(data []byte, i *int) (erlangNode, error) {
case ',':
*i++
continue
case '%':
// Starts a new comment node
continue
case ']', '}':
*i++
return out, nil
@@ -234,3 +263,19 @@ func parseErlangList(data []byte, i *int) (erlangNode, error) {
}
return out, nil
}
func parseErlangComment(data []byte, i *int) {
for *i < len(data) {
c := data[*i]
*i++
// Rest of a line is a comment. Deals with CR, LF and CR/LF
if c == '\n' {
break
} else if c == '\r' && data[*i] == '\n' {
*i++
break
}
}
}