#! /bin/jsh
#
# Copyright 2013-2014 Yuichiro Moriguchi
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
putlicense_cstyle.sh

echo '/**'
awk '{ printf(" * %s\n", $0) }' description
echo ' */'
cat definition

echo '/* @@@-PARSER-CODE-START-@@@ */'
case "$TAPETYPE" in
DFA)
  cat << EOF
function ${CLASSNAME}(rd) {
	this.reader = rd;
	this.now = rd();
	this.__state = 0;
}

${CLASSNAME}.prototype._readtape = function() {
	return this.now;
}

${CLASSNAME}.prototype._writetape = function(o) {
	this.now = o;
}

${CLASSNAME}.prototype._movetape = function(direction) {
	switch(direction) {
	case E:
		if(this.now != null)  this.now = this.reader();
		return;
	default:  throw "RuntimeException";
	}
}
EOF
  ;;
*)
  cat << EOF
function ${CLASSNAME}(rd) {
	var p = 0;
	var c;

	this._tape = [];
	while((c = rd()) != null)  this._tape[p++] = c;
	this._tapeptr = 0;
	this.__state = 0;
}

${CLASSNAME}.prototype._readtape = function() {
	if(this._tapeptr < 0 || this._tapeptr >= this._tape.length) {
		return null;
	}
	return this._tape[this._tapeptr];
}

${CLASSNAME}.prototype._writetape = function(o) {
	if(this._tapeptr >= 0 && this._tapeptr < this._tape.length) {
		this._tape[this._tapeptr] = o;
	}
}

${CLASSNAME}.prototype._movetape = function(direction) {
	switch(direction) {
	case E:
		this._tapeptr += this._tapeptr < this._tape.length ? 1 : 0;
		return;
	case W:
		this._tapeptr -= this._tapeptr >= 0 ? 1 : 0;
		return;
	default:  throw "RuntimeException";
	}
}
EOF
  ;;
esac

cat field
c='$c'
echo
cat << EOF
${CLASSNAME}.prototype._step = function($c) {
	switch(STATE) {
EOF
print_states
cat << EOF
	}
	return 0;
}

${CLASSNAME}.prototype._accepted = function() {
EOF
print_accepts
cat << EOF
	}

${CLASSNAME}.prototype._execaction = function($c) {
	switch(STATE) {
EOF
print_actions
cat << EOF
	}
	return 1;
}

${CLASSNAME}.prototype._execstep = function() {
	if(this._step(this._readtape()) != 0) {
		return false;
	} else if(this._accepted()) {
		return true;
	} else {
		throw "RuntimeException";
	}
}

${CLASSNAME}.prototype.run = function() {
	do {
		this._execaction(this._readtape());
	} while(!this._execstep());
}

${CLASSNAME}.parse = function(rd) {
	var r;

	r = new ${CLASSNAME}(rd);
	r.run();
}

${CLASSNAME}.parseStream = function(stream) {
	${CLASSNAME}.parse(function() {
		var c;

		c = stream.read();
		return c < 0 ? null : c;
	});
}

${CLASSNAME}.parseString = function(s) {
	var p = 0;

	${CLASSNAME}.parse(function() {
		return p < s.length ? s.charCodeAt(p++) : null;
	});
}

${CLASSNAME}.parseJavaString = function(s) {
	var p = 0;

	${CLASSNAME}.parse(function() {
		return p < s.length() ? s.charAt(p++) : null;
	});
}

${CLASSNAME}.parseStdin = function() {
	${CLASSNAME}.parseStream(new java.io.InputStreamReader(
			java.lang.System['in']));
}
EOF
echo '/* @@@-PARSER-CODE-END-@@@ */'

cat fragment
