Last active
July 22, 2020 08:09
-
-
Save JossWhittle/6132048 to your computer and use it in GitHub Desktop.
A BNF Grammar for the JOSS Programming Language. The JOHNNIAC Open Shop System (JOSS) was a programming language developed by the RAND Corporation between 1963-1964 to allow mathematicians and engineers to run simple yet time consuming calculations with little to no knowledge of computers and without access to a computer expert. JOSS was the fir…
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
--- Strings & Numbers --- | |
<String> := <Char> | <Char> <String> | |
<Char> := <Alpha> | <Digit> | <SpecialChar> | |
<Alpha> := "A..Z" | "a..z" | |
<SpecialChar> := "." | "," | ";" | ":" | "'" | " " | "#" | "$" | "?" | |
<Number> := <NumberPart> | <Sign> <NumberPart> | |
<NumberPart> := <IntPart> | <IntPart> "." <DecimalPart> | |
<IntPart> := "0" | <NZDigit> | <NZDigit> <DecimalPart> | |
<DecimalPart> := <Digit> | <Digit> <DecimalPart> | |
<Digit> := "0" | <NZDigit> | |
<NZDigit> := "1..9" | |
<Sign> := "+" | "-" | |
--- Dataflow --- | |
<PartNumber> := <NZDigit> | <NZDigit> <IntPart> | |
<StepNumber> := <PartNumber> "." <PartNumber> | |
--- Statements --- | |
<Statement> := <Direct> "." | <Indirect> "." | <FormCMD> | <Assignment> | |
<Direct> := <CancelCMD> | <DeleteCmdCMD> | <GoCMD> | <ArbitraryCMD> | |
<Indirect> := <StepNumber> <IndirectCMD> | |
<IndirectCMD> := <ToCMD> | <DoneCMD> | <StopCMD> | <DemandCMD> | <ArbitraryCMD> | |
<ArbitraryCMD> := <SetCMD> | <DoCMD> | <TypeCMD> | <DeleteValCMD> | <LineCMD> | <PageCMD> | |
--- Direct Statements --- | |
<GoCMD> := "Go" | |
<CancelCMD> := "Cancel" | |
<DeleteCmdCMD> := "Delete" <DelCmdSel> | |
<DelCmdSel> := <StepSel> | <PartSel> | <FormSel> | <DelCmdAllSel> | |
<DelCmdAllSel> := "all" | "all" <DelCmdAllType> | |
<DelCmdAllType> := "steps" | "parts" | "forms" | |
--- Indirect Statements --- | |
<DoneCMD> := "Done" | |
<StopCMD> := "Stop" | |
<DemandCMD> := "Demand" <Variable> | |
<ToCMD> := "To" <ToSel> | |
<ToSel> := <StepSel> | <PartSel> | |
--- Arbitrary Statements --- | |
<SetCMD> := "Set" <Assignment> | |
<DoCMD> := "Do" <DoSel> | "Do" <DoSel> <Conditional> | |
<DoSel> := <StepSel> | <PartSel> | |
<TypeCMD> := "Type" <TypeContent> | |
<TypeContent> := <TypeForm> | <TypeData> | <TypeSel> | <TypeSys> | |
<TypeSys> := "size" | "time" | "users" | |
<TypeForm> := <VarList> "in" <FormSel> | |
<TypeData> := <TypeElem> | <TypeElem> "," <TypeData> | |
<TypeElem> := """ <String> """ | <Variable> | |
<TypeSel> := <StepSel> | <PartSel> | <FormSel> | <TypeAllSel> | |
<TypeAllSel> := "all" | "all" <TypeAllType> | |
<TypeAllType> := "steps" | "parts" | "forms" | "values" | |
<DeleteValCMD> := <VarList> | "all" "values" | |
<LineCMD> := "Line" | |
<PageCMD> := "Page" | |
--- Form Statements --- | |
<FormCMD> := "Form" <PartNumber> ":" | |
<FormContent> := <FormObject> | <FormObject> <FormContent> | |
<FormObject> := <FormPH> | <String> | |
<FormPH> := <SciNotation> | <FixedNotation> | |
<SciNotation> := ".." <Dot> | |
<Dot> := "." | "." <Dot> | |
<FixedNotation> := "__" <UScore> ".__" <UScore> | |
<UScore> := "_" | "_" <UScore> | |
--- Select Statements --- | |
<StepSel> := "step" <StepNumber> | |
<PartSel> := "part" <PartNumber> | |
<FormSel> := "form" <PartNumber> | |
-- Conditional Statements --- | |
<Conditional> := <If> | <For> | |
<If> := "if" <BoolExp> | |
<BoolExp> := "(" <BoolExp> ")" | "[" <BoolExp> "]" | <Comparison> | <Comparison> <BoolOp> <BoolExp> | |
<BoolOp> := "and" | "or" | |
<Comparison> := <MathExp> <BoolComp> <MathExp> | |
<BoolComp> := "=" | "!=" | "<=" | ">=" | "<" | ">" | |
<For> := "for" <Range> | |
<Range> := <Variable> "=" <RangeExp> | |
<RangeExp> := <RangeVal> | <RangeVal> "," <RangeExp> | |
<RangeVal> := <MathExp> "(" <MathExp> ")" <RangeVal> | <MathExp> | |
--- Math Statements --- | |
<MathExp> := <Term> | <Term> <AddOp> <MathExp> | |
<Term> := <Factor> | <Factor> <MulOp> <Term> | |
<Factor> := "(" <MathExp> ")" | "[" <MathExp> "]" | <Value> | |
<Value> := <Number> | <Variable> | <Function> | |
<MulOp> := "*" | "/" | |
<AddOp> := "+" | "-" | |
--- Function --- | |
<Function> := <FuncSqrt> | <FuncLog> | <FuncExp> | <FuncSin> | <FuncCos> | <FuncIp> | | |
<FuncFp> | <FuncDp> | <FuncXp> | <FuncSgn> | <FuncMax> | <FuncMin> | |
<FuncSqrt> := "sqrt(" <MathExp> ")" | |
<FuncLog> := "log(" <MathExp> ")" | |
<FuncExp> := "exp(" <MathExp> ")" | |
<FuncSin> := "sin(" <MathExp> ")" | |
<FuncCos> := "cos(" <MathExp> ")" | |
<FuncIp> := "ip(" <MathExp> ")" | |
<FuncFp> := "fp(" <MathExp> ")" | |
<FuncDp> := "dp(" <MathExp> ")" | |
<FuncXp> := "xp(" <MathExp> ")" | |
<FuncSgn> := "sgn(" <MathExp> ")" | |
<FuncMax> := "max(" <MathExp> "," <ArgList> ")" | |
<FuncMin> := "min(" <MathExp> "," <ArgList> ")" | |
<ArgList> := <MathExp> | <MathExp> "," <ArgList> | |
--- Variables --- | |
<Variable> := <Alpha> | <Alpha> "(" <MathExp> ")" | |
<VarList> := <Variable> | <Variable> "," <VarList> |
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
start | |
= Statement | |
S | |
= [' '\t\r\n] | |
Sep | |
= S* | |
{ return ""; } | |
Seps | |
= S+ | |
{ return ""; } | |
/* | |
* Numbers | |
*/ | |
Number | |
= sign:[+-]? num:NumberPart | |
{ return parseFloat(sign + num,10); } | |
NumberPart | |
= int:("0" / NZInt) dot:("." dec:Digit+ { return "." + dec.join(""); })? | |
{ return int + dot; } | |
NZInt | |
= lead:NZDigit int:Digit* | |
{ return lead + int.join(""); } | |
Digit | |
= digit:[0-9] | |
{ return digit; } | |
NZDigit | |
= nzdigit:[1-9] | |
{ return nzdigit; } | |
/* | |
* Math | |
*/ | |
MathExp | |
= Sep l:Term Sep o:AddOp Sep r:MathExp Sep | |
{ return { tag: "math", val:{ op: o, left: l, right: r }}; } / | |
Sep l:Term Sep | |
{ return l; } | |
Term | |
= l:Factor Sep o:MulOp Sep r:Term | |
{ return { tag: "math", val:{ op: o, left: l, right: r }}; } / | |
l:Factor | |
{ return l; } | |
Factor | |
= "(" exp:MathExp ")" | |
{ return exp; } / | |
"[" exp:MathExp "]" | |
{ return exp; } / | |
v:Value | |
{ return v; } / | |
v:Function | |
{ return v; } / | |
v:Variable | |
{ return v; } | |
Value | |
= num:Number | |
{ return { tag: "num", val: num }; } | |
AddOp | |
= [+-] | |
MulOp | |
= [*/] | |
/* | |
* Strings | |
*/ | |
Alpha | |
= char:[a-zA-Z] | |
{ return char; } | |
SpecialChar | |
= char:[\.,;:' #$?] | |
{ return char; } | |
Char | |
= char:Alpha / char:Digit / char:SpecialChar | |
{ return char; } | |
String | |
= chars:Char* | |
{ return { tag: "string", val:chars.join("") }; } | |
/* | |
* Variable | |
*/ | |
Variable | |
= v:Alpha "(" i:MathExp ")" | |
{ return { tag: "var", val: { id:v, index: i }}; } / | |
v:Alpha | |
{ return { tag: "var", val: { id:v, index: { tag: "num", val: 0 } }}; } | |
VariableList | |
= v:Variable vl:(Sep "," Sep e:Variable { return e; })+ | |
{ vl.splice(0,0,v); return vl; } / | |
v:Variable | |
{ return [v]; } | |
Assignment | |
= v:Variable Sep "=" Sep exp:MathExp | |
{ return { tag: "assignment", val:{var: v, exp: exp} }; } | |
/* | |
* Functions | |
*/ | |
Function | |
= f:SingleFunction "(" exp:MathExp ")" | |
{ return { tag: "function", val: { func:f, param:exp } }; } / | |
f:MultiFunction "(" p:MathExp ps:(Sep "," Sep exp:MathExp {return exp;})+ ")" | |
{ ps.splice(0,0,p); return { tag: "function", val: { func:f, params: ps } }; } | |
SingleFunction | |
= "sqrt" / "log" / "exp" / "sin" / "cos" / "ip" / "fp" / "dp" / "xp" / "sgn" | |
MultiFunction | |
= "min" / "max" | |
/* | |
* Dataflow | |
*/ | |
PartNumber | |
= part:NZInt | |
{ return { tag: "partnumber", val: part }; } | |
StepNumber | |
= part:NZInt "." step:NZInt | |
{ return { tag: "stepnumber", val: {part:part, step:step} }; } | |
FormNumber | |
= form:NZInt | |
{ return { tag: "formnumber", val: form }; } | |
/* | |
* Select | |
*/ | |
StepSel | |
= "step" Seps num:StepNumber | |
{ return num; } | |
PartSel | |
= "part" Seps num:PartNumber | |
{ return num; } | |
FormSel | |
= "form" Seps num:FormNumber | |
{ return num; } | |
/* | |
* Statements | |
*/ | |
Statement | |
= cmd:Direct Sep "." | |
{ return { tag: "directcmd", val:cmd }; } / | |
step:StepNumber Seps cmd:Indirect Sep "." | |
{ return { tag: "indirectcmd", val:{step: step, cmd:cmd} }; } / | |
cmd:Assignment | |
{ return { tag: "assignmentcmd", val:cmd }; } / | |
cmd:FormCMD | |
{ return { tag: "formcmd", val:cmd }; } | |
Direct | |
= GoCMD / CancelCMD / DeleteCmdCMD / ArbitraryCMD | |
Indirect | |
= DoneCMD / StopCMD / DemandCMD / ToCMD / ArbitraryCMD | |
ArbitraryCMD | |
= SetCMD / DoCMD / TypeCMD / DeleteValCMD / LineCMD / PageCMD | |
/* | |
* Direct | |
*/ | |
GoCMD | |
= "Go" | |
{ return { tag: "go" }; } | |
CancelCMD | |
= "Cancel" | |
{ return { tag: "cancel" }; } | |
DeleteCmdCMD | |
= "Delete" Seps sel:DeleteCmdSel | |
{ return { tag: "delete", val: sel }; } | |
DeleteCmdSel | |
= StepSel / PartSel / FormSel / DeleteCmdAllSel / | |
vl:VariableList | |
{ return { tag: "vars", val:vl }; } | |
DeleteCmdAllSel | |
= "all" Seps type:DeleteCmdAllType | |
{ return { tag: "all", val: type }; } / | |
"all" | |
{ return { tag: "all", val: "all" }; } | |
DeleteCmdAllType | |
= "steps" / "parts" / "forms" / "values" | |
/* | |
* Indirect | |
*/ | |
DoneCMD | |
= "Done" | |
{ return { tag: "done" }; } | |
StopCMD | |
= "Stop" | |
{ return { tag: "stop" }; } | |
DemandCMD | |
= "Demand" Seps v:Variable | |
{ return { tag: "demand", val: v }; } | |
ToCMD | |
= "To" Seps sel:ToSel | |
{ return { tag: "to", val: sel }; } | |
ToSel | |
= StepSel / PartSel | |
/* | |
* Arbitrary | |
*/ | |
SetCMD | |
= "Set" Seps v:Assignment | |
{ return { tag: "set", val: v }; } | |
DoCMD | |
= "Do" Seps sel:DoSel cond:(Seps c:Conditional { return c; })? | |
{ return { tag: "do", val: {sel: sel, cond:cond} }; } | |
DoSel | |
= StepSel / PartSel | |
TypeCMD | |
= "Type" Seps sel:TypeContent | |
{ return { tag: "type", val: sel }; } | |
TypeContent | |
= TypeSys / | |
TypeSel / | |
TypeForm / | |
vl:TypeData | |
{ return { tag: "typedata", val:vl }; } | |
TypeSys | |
= "size" | |
{ return { tag: "typesize" }; } / | |
"time" | |
{ return { tag: "typetime" }; } / | |
"users" | |
{ return { tag: "typeusers" }; } | |
TypeForm | |
= v:VariableList Seps "in" Seps f:FormSel | |
{ return { tag: "typeform", val: { vars:v, form:f } }; } | |
TypeData | |
= v:TypeElem vl:(Sep "," Sep e:TypeElem { return e; })+ | |
{ vl.splice(0,0,v); return vl; } / | |
v:TypeElem | |
{ return [v]; } | |
TypeElem | |
= "\"" str:String "\"" | |
{ return str; } / | |
v:Variable | |
{ return v; } | |
TypeSel | |
= StepSel / PartSel / FormSel / TypeAllSel | |
TypeAllSel | |
= "all" Seps type:TypeAllType | |
{ return { tag: "all", val: type }; } / | |
"all" | |
{ return { tag: "all", val: "all" }; } | |
TypeAllType | |
= "steps" / "parts" / "forms" / "values" | |
DeleteValCMD | |
= "Delete" Seps sel:DeleteValSel | |
{ return { tag: "delete", val:sel }; } | |
DeleteValSel | |
= "all" Seps "values" | |
{ return { tag: "all", val: "values" }; } / | |
vl:VariableList | |
{ return { tag: "vars", val:vl }; } | |
LineCMD | |
= "Line" | |
{ return { tag: "line" }; } | |
PageCMD | |
= "Page" | |
{ return { tag: "page" }; } | |
/* | |
* Conditional | |
*/ | |
Conditional | |
= i:IfCMD | |
{ return i; } / | |
i:ForCMD | |
{ return i; } | |
IfCMD | |
= "if" Seps exp:BoolExp | |
{ return { tag: "if", val: exp }; } | |
BoolExp | |
= c:Comparison Sep o:BoolOp Sep exp:BoolExp | |
{ return { tag: "boolean", val: { op:o, left:c, right:exp } }; } / | |
c:Comparison | |
{ return c; } | |
BoolOp | |
= "and" / "or" | |
Comparison | |
= "(" Sep exp:BoolExp Sep ")" | |
{ return exp; } / | |
"[" Sep exp:BoolExp Sep "]" | |
{ return exp; } / | |
l:MathExp Sep o:BoolComp Sep r:MathExp | |
{ return { tag: "comparison", val: { op:o, left:l, right:r } }; } | |
BoolComp | |
= "=" / "!=" / "<=" / ">=" / "<" / ">" | |
ForCMD | |
= "for" Seps r:Range | |
{ return { tag: "for", val: r }; } | |
Range | |
= v:Variable Sep "=" Sep r:RangeExp | |
{ return { var:v, range:r }; } | |
RangeExp | |
= v:RangeVal vl:(Sep "," Sep e:RangeVal { return e; })+ | |
{ vl.splice(0,0,v); return vl; } / | |
v:RangeVal | |
{ return [v]; } | |
RangeVal | |
= exp:MathExp r:("(" inc:MathExp ")" target:MathExp { return { inc: inc, target: target }; })+ | |
{ return { tag: "range", val: { start: exp, targets: r } }; } / | |
exp:MathExp | |
{ return { tag: "val", val: exp }; } | |
/* | |
* Forms | |
*/ | |
FormCMD | |
= "Form" Seps form:NZInt Sep ":" | |
{ return form; } | |
FormInputCMD | |
= format:(plc:FormPlaceHolder {return plc;} / str:FormString { return str; })+ | |
{ return format; } | |
FormString | |
= chars:(Char / [=\+\*\/"])+ | |
{ return { tag: "string", val:chars.join("") }; } | |
FormPlaceHolder | |
= i:("_")+ "." f:("_")+ | |
{ var il = (i.length); var fl = (f.length); return { tag: "fixed", val: { ip: il, fp: fl } }; } / | |
"@@" ("@")+ | |
{ return { tag: "scinote" }; } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment