Platts

Platts (Programming Language for Arbitrary Two-Tag Systems) was devised in October 2008 by User:Quintopia as a way to add I/O to 2-Tag systems.

Syntax
A valid Platts program has this format: It begins with a number n followed by a newline. Following this are n production rule specifications, each followed by a newline. Everything else is considered to be the initial input to the tag system. The production rules have this syntax:



is any string of ASCII characters. Every must be the same length in characters.  is an arbitrary length string of ASCII characters, including the empty string.  must be one of these three characters:

Output Mode
When output mode is on, all strings produced by every production are echoed to output.

Input
When the program is loaded, all occurrences of the string {input} are replaced by an implementation-dependent indicator. Whenever a string containing this indicator is produced during execution, it is replaced by the next single character from user input. Replacement occurs in the logical order: from left to right in the produced string. This special string may be used in the initial input string as well, but may not be used as the for a rule. Doing so may or may cause the program to barf and die, produce unexpected results, or simply invalidate the particular rule in which it is used as such, depending on the implementation.

Implicit Production Rule Definitions
The alphabet used by any 2-Tag specified by this language is the entire ASCII alphabet. Any symbols not explicitly assigned production rules in the program listing are implicitly assigned a production of the empty string. This is another way of saying there will be no error if a symbol must be parsed for which there is no production rule specified.

Examples
Hello World: 4 A> B|Hello World! H>K K! A0B0

Cat: 4 A> B|{input} C>0A0B0C0 0! A0B0C0

Python 2
import sys from collections import defaultdict class Platts: def __init__(self, filename): self.output=False try: with open(filename,"r") as openfile: n=int(openfile.next) self.rules=defaultdict(lambda:'|') self.string='' for i in range(n): prodrule = openfile.next.strip('\n') goodrule = False self.symbolsize=1 for delim in '|>!': if delim in prodrule: if i==0: self.symbolsize=prodrule.find(delim) elif prodrule.find(delim)!=self.symbolsize: continue symbol,delim,prod = prodrule.partition(delim) self.rules[symbol] = delim+prod goodrule = True break if not goodrule: print "Bad production rule (missing delimiter or misplaced delimiter): "+prodrule sys.exit(1) for s in openfile.next: self.string+=s except IOError: print"File '%s' not found."%f sys.exit(1) def produce(self, symbol): act,prod = self.rules[symbol][0],self.rules[symbol][1:] if act=='!': self.string='' if '{input}' in prod: prod=prod.replace('{input}',sys.stdin.read(1)) if act=='>': self.output=not self.output elif self.output: sys.stdout.write(prod) return prod def cut(self): symbol = self.string[:self.symbolsize] self.string = self.string[min(self.symbolsize*2,len(self.string)):] return symbol def run(self): while len(self.string)>0: appstr=self.produce(self.cut) self.string+=appstr if __name__=="__main__": if len(sys.argv)<2: print "No filename to execute." else: Platts(sys.argv[1]).run