Skip to content

Instantly share code, notes, and snippets.

@jonasfj
Last active August 29, 2015 14:01
Show Gist options
  • Save jonasfj/c9f7b4d9a72e347aea92 to your computer and use it in GitHub Desktop.
Save jonasfj/c9f7b4d9a72e347aea92 to your computer and use it in GitHub Desktop.
Initial work on a CCS workbench implementation in Javascript

Outline for CCS Workbrench implemented in Javascript

To build parser right now run: pegjs -e "CCS.Parser" CCSParser.pegjs.

Needs:

  • Grunt script to build concat files with browserify and pegjs
  • Split large files into smaller per class files
  • HML Parser using pegjs
  • Engine that operates on subclasses of LTS.Process

Note, don't add special properties for the engine in LTS.Process. Instead use monkey patching to add the properties you need when you need them. This is more flexible and you to keep definitions clean.

/** Calculus of Communicating Systems */
(function(CCS){
/** CCS Process System
* When creating a CCS process hierarchy this class must be used to all CCS
* objects within the labelled transition system.
* All CCS objects will have a reference to this object, as the object will
* responsible for caching objects, assigning ids, etc.
* Do create a new system when creating a new labelled transition system.
*/
CCS.System = function(){
LTS.System.call(this);
this._nextProcessObjectId = 0;
this._namedStates = [];
this._namedProcessConstants = {};
this._nullProcess = new CCS.NullProcess(this);
};
CCS.System.prototype = Object.create(LTS.System.prototype);
CCS.System.prototype.constructor = CCS.System;
/** Declares an action and return CCS.Action as subclass of LTS.Action
* This method overrides LTS.System.declareAction to ensure that a
* reference to the complement action is maintained.
*/
CCS.System.prototype.declareAction = function(name){
var coname, action;
// Create action if not already exists
action = this._actionLookupTable[name];
if(!action){
// Create new action
action = new CCS.Action(name, this._nextActionId++);
// Resolve coname
if(name[0] == '\'')
coname = name.substr(1);
else
coname = '\'' + name;
// Update complement property of CCS.Action objects
action._complement = this._actionLookupTable[coname];
if(action._complement)
action._complement._complement = action;
// Store in lookup table
this._actionLookupTable[name] = action;
}
// Return action
return action;
};
/** Define a named process constant */
CCS.System.prototype.defineNamedProcess = function(name, P){
var Q;
// Create process constant (or find it in cache)
Q = this.createNamedProcess(name)
// Check if Q is already defined
if(Q._P)
throw new Error("Process constant \"" + name + "\" is already defined");
// Assign P as subprocess to Q
Q._P = P;
// Prepend to list of named states
// Using prepend ensures same ordering as in syntax
this._namedStates.unshift(Q);
};
/** Get possible initial states */
CCS.System.prototype.states = function(){
return this._namedStates;
};
/** Create null process */
CCS.System.prototype.createNullProcess = function(){
return this._nullProcess;
};
/** Create action prefix process */
CCS.System.prototype.createActionProcess = function(action, P){
var Q, cache;
// Create action process cache, if it doesn't exist
cache = P.__actionProcessCache;
if(!cache)
P.__actionProcessCache = cache = {};
// Create action prefix process, if not in cache
Q = cache[action.id()];
if(!Q)
cache[action.id()] = Q = new CCS.ActionProcess(action, P, this);
// Return prefix process
return Q;
};
/** Create named process constant */
CCS.System.prototype.createNamedProcess = function(name){
var P;
// Create process constant if it doesn't exist
P = this._namedProcessConstants[name];
if(!P){
P = new CCS.NamedProcess(name, this);
this._namedProcessConstants[name] = P;
}
// Return process constant
return P;
};
/** Create choice process */
CCS.System.prototype.createChoiceProcess = function(P, Q){
var tmp, cache, retval, order = 1;
// Avoid choice processes with null processes
if(P === this._nullProcess)
return Q;
else if(Q === this._nullProcess)
return P;
// Order P and Q, s.t.
// P.id() > Q.id() if P.id() mod 2 == Q.id() mod 2
// P.id() < Q.id() otherwise
//
// We always write the cache on P, so we always need to order
// them consistently. But we also want the cache to be reasonbly
// distributed between the two.
if((P.id() % 2) == (Q.id() % 2))
order = -1;
if((P.id() * order) < (Q.id() * order)){
tmp = P;
P = Q;
Q = tmp;
}
// Create choice process cache, if it doesn't exists
cache = P.__choiceProcessCache;
if(!cache)
P.__choiceProcessCache = cache = {};
// Create choice process, if it doesn't exists
retval = cache[Q.id()];
if(!retval)
cache[Q.id()] = retval = new CCS.ChoiceProcess(P, Q, this);
// Choice process
return retval;
};
/** Create parallel process */
CCS.System.prototype.createParallelProcess = function(P, Q){
var tmp, cache, retval, order = 1;
// Avoid parallel processes with null processes
if(P === this._nullProcess)
return Q;
else if(Q === this._nullProcess)
return P;
// Order P and Q, s.t.
// P.id() > Q.id() if P.id() mod 2 == Q.id() mod 2
// P.id() < Q.id() otherwise
//
// We always write the cache on P, so we always need to order
// them consistently. But we also want the cache to be reasonbly
// distributed between the two.
if((P.id() % 2) == (Q.id() % 2))
order = -1;
if((P.id() * order) < (Q.id() * order)){
tmp = P;
P = Q;
Q = tmp;
}
// Create parallel process cache, if it doesn't exists
cache = P.__parallelProcessCache;
if(!cache)
P.__parallelProcessCache = cache = {};
// Create parallel process, if it doesn't exists
retval = cache[Q.id()];
if(!retval)
cache[Q.id()] = retval = new CCS.ParallelProcess(P, Q, this);
// Parallel process
return retval;
};
/** Create renaming process */
CCS.System.prototype.createRenamingProcess = function(P, mappings){
var Q, mapstring, mapstrings;
// Build unique string representation of this mapping
if(!mappings.__mapstring){
// Build list of all mappings
mapstrings = [];
mappings.forEach(function(mapping){
mapstrings.push(mapping.from.name() + ' -> ' + mapping.to.name());
});
// List mappings with a comma
mappings.__mapstring = mapstrings.join(', ');
}
// Create cache if not existing
if (!P._renamingProcessCache) {
P._renamingProcessCache = {};
}
// Create renaming process, if not already in cache
Q = P._renamingProcessCache[mappings.__mapstring]
if(!Q){
Q = new CCS.RenamingProcess(P, mappings, this);
P._renamingProcessCache[mappings.__mapstring] = Q;
}
// Return renaming process
return Q;
};
/** Create restriction process */
CCS.System.prototype.createRestrictionProcess = function(P, set){
var Q, setstring, setstrings;
// Build unique string representation of this set
if(!set.__setstring){
// Build list of all actions
setstrings = [];
set.forEach(function(action){
setstrings.push(action.name());
});
// Join actions with a comma
set.__setstring = setstrings.join(', ');
}
// Create cache if not existing
if (!P._restrictionProcessCache) {
P._restrictionProcessCache = {};
}
// Create restriction process, if not already in cache
Q = P._restrictionProcessCache[set.__setstring]
if(!Q){
Q = new CCS.RestrictionProcess(P, set, this);
P._restrictionProcessCache[set.__setstring] = Q;
}
// Return restriction process
return Q;
};
/** Validate definition of all named objects */
CCS.System.prototype.validate = function(){
// Check that all named process constants are defined
Object.keys(this._namedProcessConstants).forEach(function(name){
var Q = this._namedProcessConstants[name];
if(!Q._P)
throw new CCS.ContextError(
"Named process \"" + name + "\" is not defined!",
Q.__line,
Q.__column
);
}, this);
};
/** Object for representation of an action in an CCS system
* These object must be unique within a given system,
* this is ensured by creating them with CCS.System.declareAction
*
* This function may only be called from CCS.System.
*/
CCS.Action = function(name, id){
LTS.Action.call(this, name, id);
/* the complement property is updated by CCS.System.declareAction */
this._complement = null;
};
CCS.Action.prototype = Object.create(LTS.Action.prototype);
CCS.Action.prototype.constructor = CCS.Action;
/** True, if this is an input action */
CCS.Action.prototype.isInput = function(){
return this._name[0] != '\'';
};
/** Get the complement action w.r.t. isInput
* Returns null if no such action have been declared for the current system.
*/
CCS.Action.prototype.complement = function(){
return this._complement;
};
/** Subclass of Error object to provide context errors */
CCS.ContextError = function(message, line, column){
Error.call(this, message);
this.message = message;
this.line = line;
this.column = column;
};
CCS.ContextError.prototype = Object.create(Error.prototype);
CCS.ContextError.prototype.constructor = CCS.ContextError;
/** Assign a meaning full name to this error type */
CCS.ContextError.prototype.name = 'ContextError';
/** Abstract base class for CCS processes
* Subclasses LTS.State, stores reference to CCS.Document object and
* gets a new unique identifier.
*
* May only be used by base classes, invoking it with
* CCS.Process.call(this, system);
*/
CCS.Process = function(system){
LTS.State.call(this);
this._id = system._nextProcessObjectId++;
this._system = system;
this._succ = null;
};
CCS.Process.prototype = Object.create(LTS.State.prototype);
CCS.Process.prototype.constructor = CCS.Process;
/** Get unique identifier */
CCS.Process.prototype.id = function(){
return this._id;
};
/**
* Get process successors
* Create them lazily with abstract method expand()
*/
CCS.Process.prototype.succ = function(){
if(this._succ === null)
this._succ = this.expand();
return this._succ;
}
/** Abstract function to generate successor states */
CCS.Process.prototype.expand = function(){
throw new Error("CCS.Process.expand must be implemented in base classes");
};
/** Get format identifier */
CCS.Process.prototype.format = function(){
return 'text/ccs-process';
};
/**
* Null process
* May only be called from CCS.System
*/
CCS.NullProcess = function(system){
CCS.Process.call(this, system);
};
CCS.NullProcess.prototype = Object.create(CCS.Process.prototype);
CCS.NullProcess.prototype.constructor = CCS.NullProcess;
/** Get process name */
CCS.NullProcess.prototype.name = function(){
return "0";
};
/** Generate empty set of successors */
CCS.NullProcess.prototype.expand = function(){
return [];
};
/**
* Action prefix process
* May only be called from CCS.System
*/
CCS.ActionProcess = function(action, P, system){
CCS.Process.call(this, system);
this._action = action;
this._P = P;
};
CCS.ActionProcess.prototype = Object.create(CCS.Process.prototype);
CCS.ActionProcess.prototype.constructor = CCS.ActionProcess;
/** Get process name */
CCS.ActionProcess.prototype.name = function(){
return this._action.name() + "." + this._P.name();
};
/** Generate the successor */
CCS.ActionProcess.prototype.expand = function(){
return [
{action: this._action, state: this._P}
];
};
/**
* Named Process Constant
* May only be called from CCS.System
*/
CCS.NamedProcess = function(name, system){
CCS.Process.call(this, system);
this._name = name;
// Assigned by CCS.System.defineNamedProcess
this._P = null;
};
CCS.NamedProcess.prototype = Object.create(CCS.Process.prototype);
CCS.NamedProcess.prototype.constructor = CCS.NamedProcess;
/** Get process name */
CCS.NamedProcess.prototype.name = function(){
return this._name;
};
/** Generate the successor */
CCS.NamedProcess.prototype.expand = function(){
return this._P.succ();
};
/**
* Choice Process
* May only be called from CCS.System
*/
CCS.ChoiceProcess = function(P, Q, system){
CCS.Process.call(this, system);
this._P = P;
this._Q = Q;
};
CCS.ChoiceProcess.prototype = Object.create(CCS.Process.prototype);
CCS.ChoiceProcess.prototype.constructor = CCS.ChoiceProcess;
/** Get process name */
CCS.ChoiceProcess.prototype.name = function(){
return "(" + this._P.name() + " + " + this._Q.name() + ")";
};
/** Generate the successor */
CCS.ChoiceProcess.prototype.expand = function(){
return [].concat(this._P.succ(), this._Q.succ());
};
/**
* Parallel Process
* May only be called from CCS.System
*/
CCS.ParallelProcess = function(P, Q, system){
CCS.Process.call(this, system);
this._P = P;
this._Q = Q;
};
CCS.ParallelProcess.prototype = Object.create(CCS.Process.prototype);
CCS.ParallelProcess.prototype.constructor = CCS.ParallelProcess;
/** Get process name */
CCS.ParallelProcess.prototype.name = function(){
return "(" + this._P.name() + " | " + this._Q.name() + ")";
};
/** Generate the successor */
CCS.ParallelProcess.prototype.expand = function(){
var tau, psucc, qsucc, succ = [];
// Find successors of P and Q
psucc = this._P.succ();
qsucc = this._Q.succ();
// Get reference to tau action
tau = this._system.declareAction('tau');
// For each transition in P
psucc.forEach(function(pt){
// Add transition to successor set
succ.push({
action: pt.action,
state: this._system.createParallelProcess(pt.state, this._Q)
});
}, this);
// For each transition in Q
qsucc.forEach(function(qt){
var caction;
// Add transition to successor set
succ.push({
action: qt.action,
state: this._system.createParallelProcess(qt.state, this._P)
});
// Find the complement action
caction = qt.action.complement();
// If there is a complement action, look for synchronization
if(caction){
// For each successor in p */
psucc.forEach(function(pt){
// Action in P matches complement action, we have synchronization
if(pt.action === caction){
// Add synchronization state to successor set
succ.push({
action: tau,
state: this._system.createParallelProcess(pt.state, qt.state)
});
}
}, this);
}
}, this);
return succ;
};
/**
* Renaming Process
* May only be called from CCS.System
* Mappings is a list of {from: ..., to: ...} objects
* mapping actions to other actions.
*/
CCS.RenamingProcess = function(P, mappings, system){
CCS.Process.call(this, system);
this._mappings = mappings;
this._P = P;
// Generated mapping from ids to actions, if not already cached
if(!mappings.__map){
mappings.__map = {};
mappings.forEach(function(mapping){
mappings.__map[mapping.from.id()] = mapping.to;
});
}
};
CCS.RenamingProcess.prototype = Object.create(CCS.Process.prototype);
CCS.RenamingProcess.prototype.constructor = CCS.RenamingProcess;
/** Get process name */
CCS.RenamingProcess.prototype.name = function(){
var mappings;
// Build list of all mappings
mappings = [];
this._mappings.forEach(function(mapping){
mappings.push(mapping.from.name() + ' -> ' + mapping.to.name());
});
return "(" + this._P.name() + ")[" + mappings.join(', ') + "]";
};
/** Generate the successor */
CCS.RenamingProcess.prototype.expand = function(){
// Create successors by renaming and wrapping in a renaming process
return this._P.succ().map(function(transition){
return {
action: this._mappings.__map[transition.action.id()] || transition.action,
state: this._system.createRenamingProcess(transition.state, this._mappings)
};
}, this);
};
/**
* Restriction Process
* May only be called from CCS.Document
*/
CCS.RestrictionProcess = function(P, set, system){
CCS.Process.call(this, system);
this._P = P;
this._set = set;
};
CCS.RestrictionProcess.prototype = Object.create(CCS.Process.prototype);
CCS.RestrictionProcess.prototype.constructor = CCS.RestrictionProcess;
/** Get process name */
CCS.RestrictionProcess.prototype.name = function(){
var actionNames;
// Build list of all action names
actionNames = [];
this._set.forEach(function(action){
actionNames.push(action.name());
});
return "(" + this._P.name() + ") \\ {" + actionNames.join(', ') + "}";
};
/** Generate the successor */
CCS.RestrictionProcess.prototype.expand = function(){
// Filter out transitions with actions that are restricted
return this._P.succ().filter(function(transition){
return (this._set.indexOf(transition.action) === -1);
}, this);
};
})(window.CCS = window.CCS || {});
CCS.Parser = (function() {
/*
* Generated by PEG.js 0.8.0.
*
* http://pegjs.majda.cz/
*/
function peg$subclass(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
}
function SyntaxError(message, expected, found, offset, line, column) {
this.message = message;
this.expected = expected;
this.found = found;
this.offset = offset;
this.line = line;
this.column = column;
this.name = "SyntaxError";
}
peg$subclass(SyntaxError, Error);
function parse(input) {
var options = arguments.length > 1 ? arguments[1] : {},
peg$FAILED = {},
peg$startRuleFunctions = { System: peg$parseSystem },
peg$startRuleFunction = peg$parseSystem,
peg$c0 = function() {
return system;
},
peg$c1 = peg$FAILED,
peg$c2 = "=",
peg$c3 = { type: "literal", value: "=", description: "\"=\"" },
peg$c4 = ";",
peg$c5 = { type: "literal", value: ";", description: "\";\"" },
peg$c6 = null,
peg$c7 = function(id, P) {
try{
system.defineNamedProcess(id.text, P);
}
catch (e) {
throw new CCS.ContextError(
"Named process \"" + id.text + "\" is already defined!",
id.line, id.column
);
}
},
peg$c8 = "+",
peg$c9 = { type: "literal", value: "+", description: "\"+\"" },
peg$c10 = function(P, Q) {
return system.createChoiceProcess(P, Q);
},
peg$c11 = [],
peg$c12 = function(P, processes) {
var Q;
processes.unshift(P);
while(processes.length > 1){
P = processes.shift();
Q = processes.shift();
processes.push(system.createParallelProcess(P, Q));
}
return processes[0];
},
peg$c13 = "|",
peg$c14 = { type: "literal", value: "|", description: "\"|\"" },
peg$c15 = function(P) { return P; },
peg$c16 = ".",
peg$c17 = { type: "literal", value: ".", description: "\".\"" },
peg$c18 = function(action, P) {
return system.createActionProcess(action, P);
},
peg$c19 = function(P, modifiers) {
modifiers.forEach(function(modifier){
if(modifier.isRestrict)
P = system.createRestrictionProcess(P, modifier.actions);
else
P = system.createRenamingProcess(P, modifier.mappings);
});
return P;
},
peg$c20 = "\\",
peg$c21 = { type: "literal", value: "\\", description: "\"\\\\\"" },
peg$c22 = "{",
peg$c23 = { type: "literal", value: "{", description: "\"{\"" },
peg$c24 = "}",
peg$c25 = { type: "literal", value: "}", description: "\"}\"" },
peg$c26 = function(actions) {
return {
isRestrict: true,
actions: actions
};
},
peg$c27 = "[",
peg$c28 = { type: "literal", value: "[", description: "\"[\"" },
peg$c29 = "]",
peg$c30 = { type: "literal", value: "]", description: "\"]\"" },
peg$c31 = function(mappings) {
return {
isRestrict: false,
mappings: mappings
};
},
peg$c32 = function(action, actions) {
actions.unshift(action);
return actions;
},
peg$c33 = function() { return []; },
peg$c34 = ",",
peg$c35 = { type: "literal", value: ",", description: "\",\"" },
peg$c36 = function(action) { return action; },
peg$c37 = function(mapping, mappings) {
mappings.unshift(mapping);
return mappings;
},
peg$c38 = function(mapping) { return mapping; },
peg$c39 = "->",
peg$c40 = { type: "literal", value: "->", description: "\"->\"" },
peg$c41 = function(from, to) { return {from: from, to: to}; },
peg$c42 = "(",
peg$c43 = { type: "literal", value: "(", description: "\"(\"" },
peg$c44 = ")",
peg$c45 = { type: "literal", value: ")", description: "\")\"" },
peg$c46 = "0",
peg$c47 = { type: "literal", value: "0", description: "\"0\"" },
peg$c48 = function() { return system.createNullProcess(); },
peg$c49 = function(id) {
var P = system.createNamedProcess(id.text);
if(P.__line === undefined){
P.__line = id.line;
P.__column = id.column;
}
return P;
},
peg$c50 = { type: "other", description: "identifier" },
peg$c51 = /^[A-Za-z]/,
peg$c52 = { type: "class", value: "[A-Za-z]", description: "[A-Za-z]" },
peg$c53 = /^[A-Za-z0-9_]/,
peg$c54 = { type: "class", value: "[A-Za-z0-9_]", description: "[A-Za-z0-9_]" },
peg$c55 = function(first, rest) {
return {
text: first + rest.join(''),
line: line(),
column: column()
};
},
peg$c56 = { type: "other", description: "action" },
peg$c57 = /^[A-Za-z']/,
peg$c58 = { type: "class", value: "[A-Za-z']", description: "[A-Za-z']" },
peg$c59 = function(first, rest) {
return system.declareAction(first + rest.join(''));
},
peg$c60 = { type: "other", description: "whitespace" },
peg$c61 = /^[' '\n\r\t]/,
peg$c62 = { type: "class", value: "[' '\\n\\r\\t]", description: "[' '\\n\\r\\t]" },
peg$c63 = function() {},
peg$c64 = "#",
peg$c65 = { type: "literal", value: "#", description: "\"#\"" },
peg$c66 = /^[^\n]/,
peg$c67 = { type: "class", value: "[^\\n]", description: "[^\\n]" },
peg$c68 = "\n",
peg$c69 = { type: "literal", value: "\n", description: "\"\\n\"" },
peg$c70 = void 0,
peg$c71 = /^[\S\s]/,
peg$c72 = { type: "class", value: "[^]", description: "[^]" },
peg$currPos = 0,
peg$reportedPos = 0,
peg$cachedPos = 0,
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
peg$maxFailPos = 0,
peg$maxFailExpected = [],
peg$silentFails = 0,
peg$result;
if ("startRule" in options) {
if (!(options.startRule in peg$startRuleFunctions)) {
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
}
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
}
function text() {
return input.substring(peg$reportedPos, peg$currPos);
}
function offset() {
return peg$reportedPos;
}
function line() {
return peg$computePosDetails(peg$reportedPos).line;
}
function column() {
return peg$computePosDetails(peg$reportedPos).column;
}
function expected(description) {
throw peg$buildException(
null,
[{ type: "other", description: description }],
peg$reportedPos
);
}
function error(message) {
throw peg$buildException(message, null, peg$reportedPos);
}
function peg$computePosDetails(pos) {
function advance(details, startPos, endPos) {
var p, ch;
for (p = startPos; p < endPos; p++) {
ch = input.charAt(p);
if (ch === "\n") {
if (!details.seenCR) { details.line++; }
details.column = 1;
details.seenCR = false;
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
details.line++;
details.column = 1;
details.seenCR = true;
} else {
details.column++;
details.seenCR = false;
}
}
}
if (peg$cachedPos !== pos) {
if (peg$cachedPos > pos) {
peg$cachedPos = 0;
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
}
advance(peg$cachedPosDetails, peg$cachedPos, pos);
peg$cachedPos = pos;
}
return peg$cachedPosDetails;
}
function peg$fail(expected) {
if (peg$currPos < peg$maxFailPos) { return; }
if (peg$currPos > peg$maxFailPos) {
peg$maxFailPos = peg$currPos;
peg$maxFailExpected = [];
}
peg$maxFailExpected.push(expected);
}
function peg$buildException(message, expected, pos) {
function cleanupExpected(expected) {
var i = 1;
expected.sort(function(a, b) {
if (a.description < b.description) {
return -1;
} else if (a.description > b.description) {
return 1;
} else {
return 0;
}
});
while (i < expected.length) {
if (expected[i - 1] === expected[i]) {
expected.splice(i, 1);
} else {
i++;
}
}
}
function buildMessage(expected, found) {
function stringEscape(s) {
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
return s
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\x08/g, '\\b')
.replace(/\t/g, '\\t')
.replace(/\n/g, '\\n')
.replace(/\f/g, '\\f')
.replace(/\r/g, '\\r')
.replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
}
var expectedDescs = new Array(expected.length),
expectedDesc, foundDesc, i;
for (i = 0; i < expected.length; i++) {
expectedDescs[i] = expected[i].description;
}
expectedDesc = expected.length > 1
? expectedDescs.slice(0, -1).join(", ")
+ " or "
+ expectedDescs[expected.length - 1]
: expectedDescs[0];
foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
return "Expected " + expectedDesc + " but " + foundDesc + " found.";
}
var posDetails = peg$computePosDetails(pos),
found = pos < input.length ? input.charAt(pos) : null;
if (expected !== null) {
cleanupExpected(expected);
}
return new SyntaxError(
message !== null ? message : buildMessage(expected, found),
expected,
found,
pos,
posDetails.line,
posDetails.column
);
}
function peg$parseSystem() {
var s0, s1;
s0 = peg$currPos;
s1 = peg$parseCCS();
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c0();
}
s0 = s1;
return s0;
}
function peg$parseCCS() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
s2 = peg$parseIdentifier();
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 61) {
s4 = peg$c2;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c3); }
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
s6 = peg$parseChoice();
if (s6 !== peg$FAILED) {
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 59) {
s8 = peg$c4;
peg$currPos++;
} else {
s8 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c5); }
}
if (s8 !== peg$FAILED) {
s9 = peg$parse_();
if (s9 !== peg$FAILED) {
s10 = peg$parseCCS();
if (s10 === peg$FAILED) {
s10 = peg$c6;
}
if (s10 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c7(s2, s6);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
return s0;
}
function peg$parseChoice() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
s1 = peg$parseParallel();
if (s1 !== peg$FAILED) {
s2 = peg$parse_();
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 43) {
s3 = peg$c8;
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c9); }
}
if (s3 !== peg$FAILED) {
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
s5 = peg$parseChoice();
if (s5 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c10(s1, s5);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$parseParallel();
}
return s0;
}
function peg$parseParallel() {
var s0, s1, s2, s3;
s0 = peg$currPos;
s1 = peg$parsePrefix();
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseParallelPrefix();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseParallelPrefix();
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c12(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
return s0;
}
function peg$parseParallelPrefix() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 124) {
s2 = peg$c13;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c14); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
s4 = peg$parsePrefix();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c15(s4);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
return s0;
}
function peg$parsePrefix() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
s1 = peg$parseAction();
if (s1 !== peg$FAILED) {
s2 = peg$parse_();
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 46) {
s3 = peg$c16;
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c17); }
}
if (s3 !== peg$FAILED) {
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
s5 = peg$parsePrefix();
if (s5 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c18(s1, s5);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$parsePostfix();
}
return s0;
}
function peg$parsePostfix() {
var s0, s1, s2, s3;
s0 = peg$currPos;
s1 = peg$parseAtomic();
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseModifier();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseModifier();
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c19(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$parseAtomic();
}
return s0;
}
function peg$parseModifier() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 92) {
s2 = peg$c20;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c21); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 123) {
s4 = peg$c22;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c23); }
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
s6 = peg$parseActions();
if (s6 !== peg$FAILED) {
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 125) {
s8 = peg$c24;
peg$currPos++;
} else {
s8 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c25); }
}
if (s8 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c26(s6);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 91) {
s2 = peg$c27;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c28); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
s4 = peg$parseMappings();
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 93) {
s6 = peg$c29;
peg$currPos++;
} else {
s6 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c30); }
}
if (s6 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c31(s4);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
}
return s0;
}
function peg$parseActions() {
var s0, s1, s2, s3;
s0 = peg$currPos;
s1 = peg$parseAction();
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseCommaAction();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseCommaAction();
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c32(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = [];
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c33();
}
s0 = s1;
}
return s0;
}
function peg$parseCommaAction() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 44) {
s2 = peg$c34;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c35); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
s4 = peg$parseAction();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c36(s4);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
return s0;
}
function peg$parseMappings() {
var s0, s1, s2, s3;
s0 = peg$currPos;
s1 = peg$parseMap();
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseCommaMapping();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseCommaMapping();
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c37(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = [];
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c33();
}
s0 = s1;
}
return s0;
}
function peg$parseCommaMapping() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 44) {
s2 = peg$c34;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c35); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
s4 = peg$parseMap();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c38(s4);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
return s0;
}
function peg$parseMap() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
s1 = peg$parseAction();
if (s1 !== peg$FAILED) {
s2 = peg$parse_();
if (s2 !== peg$FAILED) {
if (input.substr(peg$currPos, 2) === peg$c39) {
s3 = peg$c39;
peg$currPos += 2;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c40); }
}
if (s3 !== peg$FAILED) {
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
s5 = peg$parseAction();
if (s5 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c41(s1, s5);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
return s0;
}
function peg$parseAtomic() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 40) {
s1 = peg$c42;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c43); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parse_();
if (s2 !== peg$FAILED) {
s3 = peg$parseChoice();
if (s3 !== peg$FAILED) {
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 41) {
s5 = peg$c44;
peg$currPos++;
} else {
s5 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c45); }
}
if (s5 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c15(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 48) {
s1 = peg$c46;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c47); }
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c48();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseIdentifier();
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c49(s1);
}
s0 = s1;
}
}
return s0;
}
function peg$parseIdentifier() {
var s0, s1, s2, s3;
peg$silentFails++;
s0 = peg$currPos;
if (peg$c51.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c52); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$c53.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c54); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$c53.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c54); }
}
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c55(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c50); }
}
return s0;
}
function peg$parseAction() {
var s0, s1, s2, s3;
peg$silentFails++;
s0 = peg$currPos;
if (peg$c57.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c58); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$c53.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c54); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$c53.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c54); }
}
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c59(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c56); }
}
return s0;
}
function peg$parse_() {
var s0, s1, s2, s3, s4;
peg$silentFails++;
s0 = peg$currPos;
if (peg$c61.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c62); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parse_();
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c63();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 35) {
s1 = peg$c64;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c65); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$c66.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c67); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$c66.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c67); }
}
}
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 10) {
s3 = peg$c68;
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c69); }
}
if (s3 !== peg$FAILED) {
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c63();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 35) {
s1 = peg$c64;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c65); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$c66.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c67); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$c66.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c67); }
}
}
if (s2 !== peg$FAILED) {
s3 = peg$currPos;
peg$silentFails++;
if (peg$c71.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c72); }
}
peg$silentFails--;
if (s4 === peg$FAILED) {
s3 = peg$c70;
} else {
peg$currPos = s3;
s3 = peg$c1;
}
if (s3 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c63();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = [];
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c63();
}
s0 = s1;
}
}
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c60); }
}
return s0;
}
var system = new CCS.System();
peg$result = peg$startRuleFunction();
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
return peg$result;
} else {
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
peg$fail({ type: "end", description: "end of input" });
}
throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
}
}
return {
SyntaxError: SyntaxError,
parse: parse
};
})();
{
var system = new CCS.System();
}
System
= CCS {
return system;
}
CCS
= _ id:Identifier _ '=' _ P:Choice _ ';' _ CCS? {
try{
system.defineNamedProcess(id.text, P);
}
catch (e) {
throw new CCS.ContextError(
"Named process \"" + id.text + "\" is already defined!",
id.line, id.column
);
}
}
Choice
= P:Parallel _ '+' _ Q:Choice {
return system.createChoiceProcess(P, Q);
}
/ Parallel
Parallel
= P:Prefix processes:ParallelPrefix* {
var Q;
processes.unshift(P);
while(processes.length > 1){
P = processes.shift();
Q = processes.shift();
processes.push(system.createParallelProcess(P, Q));
}
return processes[0];
}
ParallelPrefix
= _ '|' _ P:Prefix { return P; }
Prefix
= action:Action _ '.' _ P:Prefix {
return system.createActionProcess(action, P);
}
/ Postfix
Postfix
= P:Atomic modifiers:(Modifier)* {
modifiers.forEach(function(modifier){
if(modifier.isRestrict)
P = system.createRestrictionProcess(P, modifier.actions);
else
P = system.createRenamingProcess(P, modifier.mappings);
});
return P;
}
/ Atomic
Modifier
= _ '\\' _ '{' _ actions:Actions _ '}' {
return {
isRestrict: true,
actions: actions
};
}
/ _ '[' _ mappings:Mappings _ ']' {
return {
isRestrict: false,
mappings: mappings
};
}
Actions
= action:Action actions:CommaAction* {
actions.unshift(action);
return actions;
}
/ { return []; }
CommaAction
= _ ',' _ action:Action { return action; }
Mappings
= mapping:Map mappings:CommaMapping* {
mappings.unshift(mapping);
return mappings;
}
/ { return []; }
CommaMapping
= _ ',' _ mapping:Map { return mapping; }
Map
= from:Action _ '->' _ to:Action { return {from: from, to: to}; }
Atomic
= "(" _ P:Choice _ ")" { return P; }
/ "0" { return system.createNullProcess(); }
/ id:Identifier {
var P = system.createNamedProcess(id.text);
if(P.__line === undefined){
P.__line = id.line;
P.__column = id.column;
}
return P;
}
Identifier "identifier"
= first:[A-Za-z] rest:[A-Za-z0-9_]* {
return {
text: first + rest.join(''),
line: line(),
column: column()
};
}
Action "action"
= first:[A-Za-z'] rest:[A-Za-z0-9_]* {
return system.declareAction(first + rest.join(''));
}
_ "whitespace"
= [' '\n\r\t] _ {}
/ '#' [^\n]* '\n' _ {}
/ '#' [^\n]* ![^] {}
/ {}
/** Labelled Transition System Module */
(function(LTS){
/** Auxiliary method for abstract methods */
var implementationRequired = function(){
throw new Error("Method must be implemented in subclass");
};
/** Abstract base class for implemenations of labelled transition systems
* This class keeps track of actions within a system, the method
* declareAction(name, isInput) returns an LTS.Action object for each action
* and caches this object, s.t. it'll be reused.
*/
LTS.System = function(){
this._actionLookupTable = {};
this._nextActionId = 0;
};
LTS.System.prototype.constructor = LTS.System;
/** Get a list of initial states
* This doesn't necessarily return all the states from the labelled
* transition system, but it does return all those that should be
* considered as initial states.
*/
LTS.System.prototype.states = implementationRequired;
/** Declares an action and returns an LTS.Action object for this action
*/
LTS.System.prototype.declareAction = function(name){
var action;
// Create action if not already exists
action = this._actionLookupTable[name];
if(!action){
action = new LTS.Action(name, this._nextActionId++);
// Store in lookup table
this._actionLookupTable[name] = action;
}
// Return action
return action;
};
/** Get an LTS.Action object for name, if one have been declared
* otherwise this function returns null
*/
LTS.System.prototype.getAction = function(name){
// Return action, if it exists
return this._actionLookupTable[name] || null;
};
/** Object for representation of an action in an LTS
* These object must be unique within a given system,
* this is ensured by creating them with LTS.System.declareAction
*
* This function may only be called from LTS.System
*/
LTS.Action = function(name, id){
this._name = name;
this._id = id;
};
LTS.Action.prototype.constructor = LTS.Action;
/** Get a unique action identifier */
LTS.Action.prototype.id = function(){
return this._id;
};
/** Get the name of the action */
LTS.Action.prototype.name = function(){
return this._name;
};
/** Abstract base class for implementation*/
LTS.State = function(){};
LTS.State.prototype.constructor = LTS.State;
/** Unique state identifier */
LTS.State.prototype.id = implementationRequired;
/** List of successors as objects on the form {action: ..., state: ...} */
LTS.State.prototype.succ = implementationRequired;
/** State name */
LTS.State.prototype.name = implementationRequired;
/** Mimetype of state name */
LTS.State.prototype.format = function(){
return "text/plain";
};
})(window.LTS = window.LTS || {});
<html>
<head>
<script src="LTS.js"></script>
<script src="CCS.js"></script>
<script src="CCSParser.js"></script>
</head>
<body>
<pre id="console"></pre>
<script>
// Print utility
var print = function(text) {
console.log(text);
document.getElementById('console').innerHTML += text + "\n";
};
// Parse CCS and get system
var ccs = CCS.Parser.parse('p1 = a.b.0 + c.0;');
// Find first named state declared in system as initial state
var p1 = ccs.states()[0];
// Find successor states
p1.succ().forEach(function(entry) {
print("Has action: " + entry.action.name() + " going to " + entry.state.name());
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment