Last active
March 29, 2022 16:34
-
-
Save chriskiefer/c845290eb2d8495a185fe32e342a9809 to your computer and use it in GitHub Desktop.
removing sources of ambiguity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# GRAMMAR FOR GODTI LANGUAGE | |
# (Godti? it's from Transmetropolitan) | |
# Lexer [or tokenizer] definition with language lexemes [or tokens] | |
# number: /([0-9]+\.?[0-9]*)|(\.[0-9]+)/, (//doen't work) | |
@{% | |
/* | |
examples: | |
.sy1 {=p|sawb =p} | |
~.sy1 100 | |
*/ | |
const lexer = moo.compile({ | |
commaseparator: /,/, | |
paramEnd: /\)/, | |
paramBegin: /\(/, | |
listEnd: /\]/, | |
listBegin: /\[/, | |
mappingEnd: />/, | |
mappingBeginFn: /<[mlenp]/, | |
mappingBegin: /</, | |
semicolonSeparator: /;/, | |
seqBegin: /\|\|/, | |
stepBegin: /\|:/, | |
selxBegin: /\|\\x/, | |
selBegin: /\|\\/, | |
barToken: /\|/, | |
lambdaEnd: /}/, | |
lambdaBegin: /{/, | |
dacoutCh: /\~[0-9]+/, | |
dacout: /\~/, | |
sample: { match: /\*[a-zA-Z0-9]+/, lineBreaks: true, value: x => x.slice(1, x.length)}, | |
lambdaName: {match: /\.[a-zA-Z0-9]+/, value: x => x.slice(1,x.length)}, | |
beatBarIdent: {match:/b[0-9]+b[0-9]+/, value: x => x.slice(1,x.length)}, | |
variable: {match: /=[a-zA-Z0-9]+/, value: x => x.slice(1,x.length)}, | |
fraction: /[0-9]+\/[1-9][0-9]*/, | |
number: /-?(?:[0-9]|[1-9][0-9]+)(?:\.[0-9]+)?\b/, | |
semicolon: /;/, | |
funcName: /[a-zA-Z][a-zA-Z0-9]*/, | |
string: { match: /'[a-zA-Z0-9]+'/, value: x => x.slice(1,x.length-1)}, | |
newline: { match: /\n+/, lineBreaks: true}, | |
comment: /\/\/[^\n]*/, | |
ws: { match: /\s+/, lineBreaks: true}, | |
}); | |
function mapping(d, signalIn) { | |
let val = signalIn; | |
switch(d['fn']) { | |
case 'm': | |
val = sema.synth('mul', [d['p0'], val]); | |
if (d['p1']) { | |
val = sema.synth('add', [d['p1'], val]); | |
}; | |
break; | |
case 'l': | |
val = sema.synth('blin', [ val, d['p0'], d['p1'] ]); | |
break; | |
case 'e': | |
val = sema.synth('bexp', [ val, d['p0'], d['p1'] ]); | |
break; | |
case 'n': | |
val = sema.synth('ulin', [ val, d['p0'], d['p1'] ]); | |
break; | |
case 'p': | |
val = sema.synth('uexp', [ val, d['p0'], d['p1'] ]); | |
break; | |
} | |
return val; | |
}; | |
function beatBarNum(d) { | |
let vals = d.split('b'); | |
let res = sema.synth( 'bb2ms', [{ '@float': vals[0] } ,{ '@float': vals[1] } ] ); | |
return res; | |
} | |
function sequence(seq,phase) { | |
//console.log(seq); | |
// console.log(phase); | |
//is phase a number? | |
let phasor = phase; | |
if (phase['@float']) { | |
// console.log("not a number"); | |
phasor = sema.synth('clp', [phase]); | |
} | |
let synth = sema.synth('rsq', [phasor, {'@list':seq}]); | |
return synth; | |
} | |
function stepper(trig,seq,step) { | |
// console.log(seq); | |
// console.log(step); | |
// console.log(trig); | |
let synth = sema.synth('step', [trig, {'@list':seq}, step]); | |
return synth; | |
} | |
function select(idx,seq) { | |
//console.log(seq); | |
//console.log(idx); | |
let synth = sema.synth('sel', [idx, {'@list':seq}]); | |
return synth; | |
} | |
function selectx(idx,seq) { | |
console.log(seq); | |
console.log(idx); | |
let synth = sema.synth('selx', [idx, {'@list':seq}]); | |
return synth; | |
} | |
%} | |
# Pass your lexer object using the @lexer option | |
@lexer lexer | |
# Grammar definition in the Extended Backus Naur Form (EBNF) | |
main -> Statement | |
{% d => ( { '@lang' : d[0] } ) %} | |
#statement is one or more expressions | |
Statement -> | |
_ Expression _ | |
{% d => [ { '@spawn': d[1] } ] %} | |
| | |
_ Expression _ %newline | |
{% d => [ { '@spawn': d[1] } ] %} | |
| | |
_ Expression _ %newline _ Statement | |
{% d => [ { '@spawn': d[1] } ].concat(d[5]) %} | |
| | |
%comment %newline:* Statement | |
{% d => d[2] %} | |
Lambda -> | |
%lambdaBegin _ LambdaVarBlock _ Expression _ %lambdaEnd | |
{% d=> ({ | |
'@lambda': | |
{'vars':d[2], | |
'tree':d[4]} | |
}) %} | |
LambdaVarBlock -> LambdaVarList _ %barToken | |
{% d => (d[0] ) %} | |
LambdaVarList -> | |
_ | |
{% d=> [] %} | |
| | |
%variable | |
{% d => ( [ d[0] ] ) %} | |
| | |
%variable _ %commaseparator _ LambdaVarList | |
{% d => [ d[0] ].concat(d[4]) %} | |
Expression -> | |
%funcName __ ParamElement | |
{% d => sema.synth( d[0].value, [d[2]]) %} | |
| | |
Mapping _ %funcName __ ParamElement | |
{% | |
d => mapping(d[0], sema.synth( d[2].value, [d[4]]) ) | |
%} | |
| | |
%funcName _ ParameterList _ ParamElement | |
{% d => sema.synth( d[0].value, [d[4]].concat(d[2]['@params']) ) %} | |
| | |
Mapping _ %funcName _ ParameterList _ ParamElement | |
{% d => mapping(d[0], sema.synth( d[2].value, [d[6]].concat(d[4]['@params']) )) %} | |
| | |
%lambdaName _ Lambda | |
{% d => sema.setvar( d[0].value, d[2] ) %} | |
| | |
%lambdaName _ ParamElement | |
{% d => ( { '@lambdacall': {'params':[d[2]], 'lambda':d[0] }} ) %} | |
| | |
%lambdaName _ ParameterList _ ParamElement | |
{% d => ( { '@lambdacall': {'params':[d[4]].concat(d[2]['@params']), 'lambda':d[0] }} ) %} | |
| | |
%variable _ Expression | |
{% d => sema.setvar( d[0].value, d[2] ) %} | |
| | |
%sample _ ParamElement | |
{% d => sema.synth( 'sampler', [d[2], sema.str(d[0].value)] ) %} | |
| | |
%sample _ ParameterList _ ParamElement | |
{% d => sema.synth( 'sampler', [d[4]].concat(d[2]['@params']).concat([sema.str(d[0].value)]) ) %} | |
| | |
Mapping _ %sample _ ParamElement | |
{% d => mapping(d[0], sema.synth( 'sampler', [d[4], sema.str(d[2].value)] )) %} | |
| | |
Mapping _ %sample _ ParameterList _ ParamElement | |
{% d => mapping(d[0], sema.synth( 'sampler', [d[6]].concat(d[4]['@params']).concat([sema.str(d[2].value)]) ) ) %} | |
| | |
%dacout _ Expression | |
{% d => sema.synth( 'dac', [d[2]] ) %} | |
| | |
%dacoutCh __ Expression | |
{% d => sema.synth( 'dac', [d[2], sema.num(d[0].value.substr(1))] ) %} | |
# | | |
# %seqBegin _ SeqParams _ %semicolonSeparator _ %number _ %seqEnd | |
# {% d=> sequence(d[2],{ '@float': d[6].value }) %} | |
| | |
%seqBegin _ SeqParams _ %semicolonSeparator _ ParamElement _ %barToken | |
{% d=> sequence(d[2],d[6]) %} | |
| | |
%stepBegin _ SeqParams _ %semicolonSeparator _ ParamElement _ %semicolonSeparator _ ParamElement _ %barToken | |
{% d=> stepper(d[10], d[2], d[6]) %} | |
| | |
%selBegin _ SeqParams _ %semicolonSeparator _ ParamElement _ %barToken | |
{% d=> select(d[6],d[2]) %} | |
| | |
%selxBegin _ SeqParams _ %semicolonSeparator _ ParamElement _ %barToken | |
{% d=> selectx(d[6],d[2]) %} | |
ParameterList -> | |
%paramBegin Params %paramEnd | |
{% d => ( {'@params': d[1]} ) %} | |
| | |
%paramBegin _ %paramEnd | |
{% d => ( { '@params': []} ) %} | |
Params -> | |
ParamElement | |
{% d => ( [ d[0] ] ) %} | |
| | |
ParamElement _ %commaseparator _ Params | |
{% d => [ d[0] ].concat(d[4]) %} | |
SeqParams -> | |
ParamElement | |
{% d => ( [ d[0] ] ) %} | |
| | |
ParamElement __ SeqParams | |
{% d => [ d[0] ].concat(d[2]) %} | |
ParamElement -> | |
BeatBarNum | |
{% id %} | |
| | |
%number | |
{% d => ( { '@float': d[0].value } ) %} | |
| | |
%fraction | |
{% d => ( { '@float': d[0].value } ) %} | |
| | |
%string | |
{% d => ( { '@string': d[0].value } ) %} | |
| | |
%variable | |
{% d => sema.getvar( d[0].value ) %} | |
| | |
Mapping _ %variable | |
{% d => mapping(d[0], sema.getvar( d[2].value )) %} | |
| | |
%listBegin Params %listEnd | |
{% d => ( { '@list': d[1] } )%} | |
| | |
Expression | |
{% id %} | |
Mapping -> | |
%mappingBegin _ %mappingEnd | |
{% d => ({'fn': 'none'}) %} | |
| | |
%mappingBegin _ %number _ %mappingEnd | |
{% d => ({'fn': 'm', 'p0': { '@float': d[2].value }}) %} | |
| | |
%mappingBegin _ %number _ %semicolonSeparator _ %number _ %mappingEnd | |
{% d => ({'fn': 'l', 'p0': { '@float': d[2].value }, 'p1': { '@float': d[6].value }}) %} | |
| | |
%mappingBeginFn _ %number _ %semicolonSeparator _ %number _ %mappingEnd | |
{% d => ({'fn': d[0].value[1], 'p0': { '@float': d[2].value }, 'p1': { '@float': d[6].value }}) %} | |
BeatBarNum -> _ %beatBarIdent _ | |
{% d=> (beatBarNum(d[1].value)) %} | |
# Whitespace | |
_ -> wschar:* | |
{% function(d) {return null;} %} | |
__ -> wschar:+ | |
{% function(d) {return null;} %} | |
wschar -> %ws | |
{% id %} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment