S-expressions: Difference between revisions

m
m (syntax highlighting fixup automation)
 
(6 intermediate revisions by 5 users not shown)
Line 3,839:
 
=={{header|JavaScript}}==
(for a '''bug-fix''' concerning \" and \n in strings see the [[Talk:S-expressions#JavaScript_version_bugfix_for_%5C%22_and_%5Cn_in_strings|Discussion]])
===Procedural===
<syntaxhighlight lang="javascript">String.prototype.parseSexpr = function() {
Line 3,918 ⟶ 3,919:
"((data \"quoted data\" 123 4.5)",
" (data (!@# (4.5) \"(more\" \"data)\")))"
].join("\n");
) : .join("\n");
 
const [parse, residue] = parseExpr(
Line 3,924 ⟶ 3,926:
);
 
return 0 < residue.length ? (
? `Unparsed tokens: ${JSON.stringify(residue)}`
) : 0 < parse.length ? ([
JSON.stringify(parse, null, 2), ? [
"Reserialized from JSON.stringify(parse:", null, 2),
parse.map(serialized).join( "Reserialized from parse:"),
parse.map(serialized).join(" ")
].join("\n\n")) : "Could not be parsed";
) : parseFloat(s, 10) ]
.join("\n\n")
].join("\n\n")) : "Could not be parsed";
};
 
Line 3,959 ⟶ 3,964:
// An open bracket introduces recursion over
// a sub-expression to define a sub-list.
return "(" === token ? (() => {
const? [expr, rest](() => parseExpr(ts);{
const [expr, rest] = parseExpr(ts);
 
return [xs.concat([expr]), rest.slice(1)];
})() : ")" === token ? })()
[xs,: ")" === token]
) : ? [xs.concat(atom(token)), tstoken];
: [xs.concat(atom(token)), ts];
};
 
Line 3,972 ⟶ 3,979:
// atom :: String -> Expr
const atom = s =>
0 < s.length ? (
? isNaN(s) ? (
? "\"'".includes(s[0]) ? (
? s.slice(1, -1)
) : {name: s}
name: parseFloat(s, 10)
: }"";
) : parseFloat(s, 10)
) : "";
 
 
Line 3,989 ⟶ 3,994:
// Brackets and quoted or unquoted atomic strings.
quoteTokens("\"")(s).flatMap(
segment => "\"" !== segment[0] ? (
? segment.replace(/([()])/gu, " $1 ")
.split(/\s+/u)
.filter(Boolean)
) : [segment]
);
 
Line 4,001 ⟶ 4,006:
// Alternating unquoted and quoted segments.
s => s.split(q).flatMap(
(k, i) => even(i) ? (
Boolean(k) ? (0 < k.length
? [k]
) : []
) : [`${q}${k}${q}`]
);
 
Line 4,014 ⟶ 4,019:
const t = typeof e;
 
return "number" === t ? (
? `${e}`
) : "string" === t ? (
? `"${e}"`
) : "object" === t ? (
? Array.isArray(e) ? (
? `(${e.map(serialized).join(" ")})`
) : e.name
) : "?";
};
 
Line 4,041 ⟶ 4,046:
f => {
const go = x =>
p(x) ? x : go(f(x));
? x
: go(f(x));
 
return go;
Line 4,080 ⟶ 4,087:
 
((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'''
[[Category:PEG]]
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}}==
Line 4,571 ⟶ 4,651:
 
=={{header|OCaml}}==
You may be interested byin this [https://dev.realworldocaml.org/v1/en/html/data-serialization-with-s-expressions.html this chapter of the book Real World OcamlOCaml].
 
You may be interested by [https://realworldocaml.org/v1/en/html/data-serialization-with-s-expressions.html this chapter of the book Real World Ocaml]
 
The file <code>SExpr.mli</code> containing the interface:
Line 6,713 ⟶ 6,792:
{{libheader|Wren-pattern}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="ecmascriptwren">import "./pattern" for Pattern
import "./fmt" for Fmt
 
var INDENT = 2
9,655

edits