S-expressions: Difference between revisions

Content added Content deleted
m (syntax highlighting fixup automation)
Line 4,080: Line 4,080:


((data "quoted data" 123 4.5) (data (!@# (4.5) "(more" "data)")))</pre>
((data "quoted data" 123 4.5) (data (!@# (4.5) "(more" "data)")))</pre>

=={{header|jq}}==
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq'''

This entry is based on a Parsing Expression Grammar (PEG) for S-expressions.
The idea is to pass a JSON object `{remainder:_, result:_ }` through a
jq pipeline corresponding to a PEG for S-expressions, consuming the
text in `.remainder` and building up `.result`.
For further details about this approach, see e.g.
[https://github.com/stedolan/jq/wiki/Parsing-Expression-Grammars jq as a PEG Engine].
<syntaxhighlight lang=jq>
# PEG infrastructure
def star(E): ((E | star(E)) // .) ;

### Helper functions:
# Consume a regular expression rooted at the start of .remainder, or emit empty;
# on success, update .remainder and set .match but do NOT update .result
def consume($re):
# on failure, match yields empty
(.remainder | match("^" + $re)) as $match
| .remainder |= .[$match.length :]
| .match = $match.string;

def parse($re):
consume($re)
| .result = .result + [.match] ;

def parseNumber($re):
consume($re)
| .result = .result + [.match|tonumber] ;

def eos: select(.remainder == "");

# whitespace
def ws: consume("[ \t\r\n]*");

def box(E):
((.result = null) | E) as $e
| .remainder = $e.remainder
| .result += [$e.result] # the magic sauce
;

# S-expressions

# Input: a string
# Output: an array representation of the input if it is an S-expression
def SExpression:
def string: consume("\"") | parse("[^\"]") | consume("\"");
def identifier: parse("[^ \t\n\r()]+");
def decimal: parseNumber("[0-9]+([.][0-9]*)?");
def hex: parse("0x[0-9A-Fa-f]+") ;
def number: hex // decimal;
def atom: ws | (string // number // identifier);

def SExpr: ws | consume("[(]") | ws | box(star(atom // SExpr)) | consume("[)]");

{remainder: .} | SExpr | ws | eos | .result;

SExpression
</syntaxhighlight>
'''Invocation:'''
<pre>
cat << EOF |
((data "quoted data" 123 4.5)
(data (!@# (4.5) "(more" "data)")))
EOF
jq -Rsc -f s-expression.jq
</pre>
{{output}}
<pre>
[[["data","\"quoted","data\"",123,4.5],["data",["!@#",[4.5],"\"",["more\"","\"data"],"\""]]]]
</pre>


=={{header|Julia}}==
=={{header|Julia}}==