Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/shimpe/scparco
Quark providing parser combinators for supercollider
https://github.com/shimpe/scparco
parsing sclang supercollider
Last synced: about 5 hours ago
JSON representation
Quark providing parser combinators for supercollider
- Host: GitHub
- URL: https://github.com/shimpe/scparco
- Owner: shimpe
- License: gpl-3.0
- Created: 2023-05-27T05:49:36.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-02-17T17:29:35.000Z (9 months ago)
- Last Synced: 2024-02-17T18:33:14.912Z (9 months ago)
- Topics: parsing, sclang, supercollider
- Language: SuperCollider
- Homepage:
- Size: 769 KB
- Stars: 4
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# scparco
GPLv3 Library of parser combinators for supercollider. It can be used with text (modeled as a string) or binary data (contained in an Int8Array).Example of parsing binary data from a sysex message:
```smalltalk
(
var t = Int8Array[0xF7, 0x00, 0x01, 0x41, 0xF0]; // contrived example containing only manufacturer's id
var startOfSysex = ScpParserFactory.makeBinaryLiteralInt8ArrayParser(Int8Array[0xF7]);
var manufacturerId = ScpParserFactory.makeBinaryUIntParser(8).chain({
| result |
// using chain we can influence the next parser:
// if the first byte is 0x00, two more bytes will follow with the manufacturer id
// otherwise, the byte value itself is already the manufacturer's id
if (result == 0) {
// extract extended ID and tag it as \manufacturerId in the parse result
ScpParserFactory.makeBinaryUIntParser(16).map(ScpMapFactory.tag(\manufacturerId));
} {
// current byte value is already the ID; tag it as \manufacturerId in the parse result
ScpSucceedParser(result).map(ScpMapFactory.tag(\manufacturerId));
}
});
var sysexParser = ScpSequenceOf([startOfSysex, manufacturerId]).map({|result| result[1] }); // keep only manufacturer's id
var result = sysexParser.run(t);
result.result.postcs;
)
```A non-trivial example for parsing and evaluating a mathematical expresssion from text:
```smalltalk
(
// simple calculator
// first the parser
var numberParser = ScpParserFactory.makeFloatParser.map({|x| (\type : \number, \value : x) });
var operatorParser = ScpChoice([ScpStrParser("+"), ScpStrParser("-"), ScpStrParser("*"), ScpStrParser("/")]);
var betweenBrackets = ScpParserFactory.makeBetween(ScpStrParser("("), ScpStrParser(")"));
var expression = ScpParserFactory.forwardRef(Thunk({
ScpChoice([
numberParser,
operationParser
])
}));
var operationParser = betweenBrackets.(ScpSequenceOf([
operatorParser,
ScpParserFactory.makeWs,
expression,
ScpParserFactory.makeWs,
expression
])).map({ |results| (\type: \operation, \value : (\op : results[0], \a : results[2], \b : results[4]) ) });// then an evaluator to perform the actual calculations based on the parsing result
var evaluate = {
| node |
if (node[\type] == \number) {
node[\value];
} {
if (node[\type] == \operation) {
if (node[\value][\op].compare("+") == 0) {
thisFunction.(node[\value][\a]) + thisFunction.(node[\value][\b]); //recursion
} {
if (node[\value][\op].compare("-") == 0) {
thisFunction.(node[\value][\a]) - thisFunction.(node[\value][\b]);
} {
if (node[\value][\op].compare("*") == 0) {
thisFunction.(node[\value][\a]) * thisFunction.(node[\value][\b]);
} {
if (node[\value][\op].compare("/") == 0) {
thisFunction.(node[\value][\a]) / thisFunction.(node[\value][\b]);
}
}
}
}
}
};
};var interpreter = {
| program |
// first parse the program, then evaluate it
var parseResult = expression.run(program);
if (parseResult.isError) {
"Invalid program".postln;
nil;
} {
evaluate.(parseResult.result);
}
};// try it out
var program = "(+ (* 10 2) (- (/50 3) 2))";
var result = interpreter.(program);
result.debug("result of the calculation");
)
```