javacc_input ::= javacc_options
"PARSER_BEGIN" "(" ")"
java_compilation_unit
"PARSER_END" "(" ")"
( production )*
The grammar file starts with a list of options (which is optional). This is then followed by a Java compilation unit enclosed between "PARSER_BEGIN(name)" and "PARSER_END(name)". After this is a list of grammar productions which consist of the listing of the BNF notation for a generic Rescue-Retry. The name that follows "PARSER_BEGIN" and "PARSER_END" must be the same and this identifies the name of the generated parser. For example, if name is MyParser, then the following files are generated:
MyParser.java: The generate parser.
MyParserTokenManager.java: The generated token manager (or scanner/lexical analyzer)
MyParserConstants.java: A bunch of useful constants
To illustrate these explanations, an example for the use of the Rescue-Retry construct follows:
Protected int tx_failures;
/* Initialize to zero in an init function */
Public boolean tx_succesful;
/* Attempt to transmit the message 100 times and set "tx_succesful" accordingly */
Public void transmit_message(String message ) {
If tx_failures < 100
{
attempt_transmission(message);
tx_succesful = true;
}
else tx_succesful = false;
rescue
{
tx_failures = tx_failures + 1;
retry;
}
In the Appendix, we also listed part of the code for the back-end which generates the Java output file.(in Bytes) |
(in second) |
..(in second) |
(in second) |
|
(without Jass) |
UnlimitedBuffer.class 1,282 |
|||
(with Jass) |
UnlimitedBuffer.class 3,854 |
java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
at java.util.Vector.elementAt(Vector.java)
at jass.purejava.UnlimitedBuffer.remove(UnlimitedBuffer.java:25)
at jass.purejava.BufferTest.main(BufferTest.java:20)
... which means the exception is logically not detected by our program, but is caught by the handler of java.util.Vector class.
jass.runtime.LoopInvariantException: jass.purejava.BufferTest.main([Ljava.lang.String;):17
at jass.purejava.BufferTest.main(BufferTest.java:28)
java.lang.ArithmeticException: / by zero
at jass.examples.BufferTest.foo(BufferTest.java:24)
at jass.examples.BufferTest.main(BufferTest.java:32)
jass.runtime.RefinementException: jass.examples.UnlimitedBuffer
at jass.examples.UnlimitedBuffer.jassCheckInvariant(UnlimitedBuffer.java:119)
at jass.examples.UnlimitedBuffer.add(UnlimitedBuffer.java:45)
at jass.examples.BufferTest.foo(BufferTest.java:12)
at jass.examples.BufferTest.main(BufferTest.java:32)
jass.runtime.PostconditionException: jass.examples.Buffer.full()
at jass.examples.Buffer.full(Compiled Code)
at jass.examples.Producer.run(Compiled Code)
jass.runtime.PostconditionException:
jass.examples.Buffer.add(java.lang.Object)
at jass.examples.Buffer.add(Buffer.java:61)
at jass.examples.Producer.run(Compiled Code)
jass.runtime.PostconditionException: jass.examples.Buffer.empty()
at jass.examples.Buffer.empty(Compiled Code)
at jass.examples.Producer.run(Compiled Code)
void MethodBodyBlock() :
{}
{
[ RequireClause() ] ( BlockStatement() )* [ EnsureClause() ] [ RescueClause() ]
}
void AssertionClause() :
{}
{
[ InvariantClause() ] [ VariantClause() ] Statement()
}
void RequireClause() :
{}
{
<REQUIRE> ( BooleanAssertion() ";" )+ <ASS_END>
}
void EnsureClause() :
{}
{
<ENSURE> ( BooleanChangeAssertion() ";" )+ <ASS_END>
}
void BooleanAssertion() :
{}
{
LOOKAHEAD ( AssertionLabel() ) AssertionLabel() AssertionExpression() | AssertionExpression()
}
void BooleanChangeAssertion() :
{}
{
LOOKAHEAD ( <CHANGEONLY> ) <CHANGEONLY> "{" [ ChangeList() ] "}" | BooleanAssertion()
}
void ChangeList() :
{}
{
FieldReference() ( "," FieldReference() )*
}
void FieldReference() :
{}
{
[ "this" "." ] <IDENTIFIER>
}
void AssertionLabel() :
{}
{
"[" <IDENTIFIER> [ ":" AssertionExpression() ] "]"
}
void ClassInvariantClause() :
{}
{
<INVARIANT> ( BooleanAssertion() ";" )+ <ASS_END>
}
void InvariantClause() :
{}
{
<INVARIANT> ( BooleanAssertion() ";" )+ <ASS_END>
}
void CheckClause() :
{}
{
<CHECK> ( BooleanAssertion() ";" )+ <ASS_END>
}
void RescueClause() :
{}
{
<RESCUE> [ ( RescueCatch() ";" )+ ] | [ RescueRetry() ] <ASS_END>
}
void RescueCatch() :
{}
{
"catch" "(" FormalParameter() ")" "{" ( BlockStatement() | RetryStatement() )* "}"
}
void RescueRetry() :
{}
{
RetryStatement() ";"
}
public Object visit(RescueCatch node, Object vi) {
/* RescueCatch ::= ("catch" "(" FormalParameter ")")? "{" ( BlockStatement | RetryStatement )* "}" */
boolean retry = false;
if (node.getFirstToken().image == "catch") {
FormalParameter p = (FormalParameter)node.jjtGetChild(0).jjtAccept(this,vi);
((VInfo)vi).rescues.addElement(p);
// look for a retry (important info for code generation !)
for (int i = 1; i < node.jjtGetNumChildren(); i++)
if (node.jjtGetChild(i).hasId(JJTRETRYSTATEMENT)) {
retry = true;
}
} else
{
Class type = ClassPool.getClass("RuntimeException");
String name = new String();
name = "e";
FormalParameter p = new FormalParameter();
p.setType(type);
p.setName(name);
p.setModifier(0);
System.out.println(p.toString());
((VInfo)vi).rescues.addElement(p);
// look for a retry (important info for code generation !)
for (int i = 0; i < node.jjtGetNumChildren(); i++)
if (node.jjtGetChild(i).hasId(JJTRETRYSTATEMENT)) {
retry = true;
}
}
if (retry) ((VInfo)vi).retries.addElement(Boolean.TRUE);
else ((VInfo)vi).retries.addElement(Boolean.FALSE);
return null;
}
public Object visit(RescueCatch node, Object vinfo) {
VInfo vi = (VInfo)vinfo;
out.println();
out.print(vi.method_indent+"\t");
// print "catch" "("
printComments(node.getFirstToken(),vi);
out.print("catch");
if (node.getFirstToken().image != "catch") {
out.print("( RuntimeException e )");
// print "{"
print(node.getFirstToken(),vi);
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
node.jjtGetChild(i).jjtAccept(this,vi);
}
} else
{
print(node.getFirstToken().next,vi);
print((SimpleNode)node.jjtGetChild(0),vi);
// print ")"
print(node.jjtGetChild(0).getLastToken().next,vi);
// print "{"
print(node.jjtGetChild(0).getLastToken().next.next,vi);
for (int i = 1; i < node.jjtGetNumChildren(); i++) {
node.jjtGetChild(i).jjtAccept(this,vi);
}
}
if (!vi.m.getRetries()[vi.rescueCounter].equals(Boolean.TRUE)) {
out.println();
out.print(vi.method_indent+"\t\tthrow "+vi.m.getRescues()[vi.rescueCounter].getName()+";");
print(node.getLastToken(),vi);
} else
{
print(node.getLastToken(),vi);
}
vi.rescueCounter++;
return null;
}
public Object visit(RetryStatement node, Object vi) {
printSpecials(node.getFirstToken(),vi);
out.print("flagRetry = true; continue Retry;");
return null;
}
package jass.examples;
public class Buffer implements Cloneable {
protected int in,out;
protected Object[] buffer;
public Buffer() {
buffer = new Object[0];
}
public Buffer (int anzahl) {
/** require anzahl > 0; **/
buffer = new Object[anzahl];
/** ensure buffer.length == anzahl; **/
}
public boolean empty() {
return in - out == 0;
/** ensure changeonly{}; **/
}
public boolean full() {
return in - out == buffer.length;
/** ensure changeonly{}; **/
}
public void add(Object o) {
/** require [valid_object] o != null; [buffer_not_full] !full(); **/
buffer[in % buffer.length] = o;
in++;
/** ensure changeonly{in,buffer}; Old.in == in - 1; **/
}
public Object remove() {
/** require [buffer_not_empty] !empty(); **/
Object o = buffer[out % buffer.length];
out++;
return o;
/** ensure changeonly{out}; [valid_object] Result != null; **/
}
public boolean contains(Object o) {
/** require o != null; **/
boolean found = false;
for (int i = 0; i < buffer.length; i++)
/** invariant 0 <= i && i <= buffer.length; **/
/** variant buffer.length - i **/
if (buffer[i].equals(o)) found = true;
return found;
/** ensure changeonly{}; **/
}
protected Object clone() {
/* Use the Objects clone method. This is enough cause only in and out are refered with Old expressions. */
Object b = null;
try {
b = super.clone();
}
catch (CloneNotSupportedException e){;}
return b;
}
/** invariant [range] 0 <= in - out && in - out <= buffer.length;
[valid_content] buffer.length == 0 || (forall i : {out%buffer.length .. in%buffer.length-1} # buffer[i] != null); **/
}
package jass.examples;
public class UnlimitedBuffer extends Buffer implements jass.runtime.Refinement {
protected java.util.Vector v = new java.util.Vector();
public boolean empty() {
return v.size() == 0;
/** ensure changeonly{}; **/
}
public boolean full() {
return false;
/** ensure changeonly{}; **/
}
public synchronized void add(Object o) {
/** require [valid_object] o != null; **/
v.addElement(o);
/** ensure Old.v.size() == v.size()-1;**/
}
public synchronized Object remove() {
/** require [buffer_not_empty] !empty(); **/
Object o = v.elementAt(0);
v.removeElementAt(0);
return o;
/** ensure [valid_object] Result != null; **/
}
public synchronized boolean contains(Object o) {
/** require o != null; **/
return v.contains(o);
/** ensure changeonly{}; **/
}
protected Object clone() {
java.util.Vector h = new java.util.Vector();
for (int i = 0; i < v.size(); i++) h.addElement(v.elementAt(i));
UnlimitedBuffer ub = new UnlimitedBuffer();
ub.v = h;
return ub;
}
private Buffer jassGetSuperState() {
Buffer b = new Buffer(v.size()+1);
b.in = v.size();
b.out = 0;
for (int i = 0; i < b.buffer.length-1; i++)
b.buffer[i] = v.elementAt(i);
return b;
}
/** invariant forall i : { 0 .. v.size()-1 } # v.elementAt(i) != null; **/
}
package jass.examples;
public class BufferTest {
public static void main (String[] as) {
UnlimitedBuffer b = new UnlimitedBuffer();
int i;
for ( i = 1; i< 1000; i ++ ){
b.add(new Integer(i));
}
for ( i = 1; i<=1000; i++ ) {
System.out.println(b.remove());
}
}
}
package jass.examples;
public class BufferTest {
static void foo ( Buffer b ) {
int i;
for ( i = 1; i< 100; i ++ ){
b.add(new Integer(i));
}
b.add( null );
for ( i = 1; i<=100; i++ )
{
Object kk;
String dds;
int ii;
kk = b.remove();
dds = kk.toString();
ii = Integer.parseInt( dds.trim() );
System.out.println(100/ii);
}
}
public static void main (String[] as) {
UnlimitedBuffer b = new UnlimitedBuffer();
foo( b );
}
}
package jass.examples;
public class Consumer extends Thread {
protected Buffer cbuffer;
public Consumer (Buffer buffer) {
this.cbuffer = buffer;
}
public synchronized void run () {
for (int i = 0;i < 100;) {
if (!cbuffer.empty()) {
System.out.println(cbuffer.remove()+" <--");
i++;
}
}
}
}
package jass.examples;
public class Producer extends Thread {
protected Buffer pbuffer;
public Producer (Buffer buffer) {
this.pbuffer = buffer;
}
public synchronized void run () {
for (int i = 0;i<100;) {
if (!pbuffer.full()) {
System.out.println("--> "+i);
pbuffer.add(new Integer(i++));
}
}
}
}
package jass.examples;
public class ProducerConsumer {
protected static Producer producer;
protected static Consumer consumer;
protected static Buffer buffer;
public static void main (String[] args) {
buffer = new Buffer(7);
producer = new Producer(buffer);
consumer = new Consumer(buffer);
producer.start();
consumer.start();
}
}
package jass.examples;
public class Server {
protected Buffer TxBuffer;
protected Buffer RxBuffer;
protected int j;
public Server (Buffer buffer1, Buffer buffer2) {
this.TxBuffer = buffer1;
this.RxBuffer = buffer2;
}
public void Transmit () {
for (int i = 0;i<10;) {
Attempt_Transmission("TestMessage");
i++;
}
Check_Ack();
/** rescue
{
System.out.println("Transmit Messages Lost- Attempting Retransmit");
retry;
}; **/
}
public void Check_Ack () {
for (int i = 0;i<10;) {
Receive_Ack();
i++;
}
}
private void Attempt_Transmission(String TxString) {
if (!TxBuffer.full()) {
System.out.println("--> TestMessage");
TxBuffer.add(new String("TestMessage"));
}
}
private void Receive_Ack() {
// if(!RxBuffer.empty()) {
System.out.println("<-- Ack");
RxBuffer.remove();
// }
// else throw(java.lang.RuntimeException);
}
}
package jass.examples;
public class Client {
protected Buffer cbuffer;
protected int j;
public Client (Buffer buffer) {
this.cbuffer = buffer;
}
public void Init () {
for (int i = 0;i < 5;) {
cbuffer.add(new String("ack") );
i++;
}
}
}
package jass.examples;
public class ClientServer {
protected static Client client;
protected static Server server;
protected static Buffer TxBuffer;
protected static Buffer AckBuffer;
public static void main (String[] args) {
TxBuffer = new Buffer(10);
AckBuffer = new Buffer(10);
server = new Server(TxBuffer, AckBuffer);
client = new Client(AckBuffer);
client.Init();
server.Transmit();
}
}
|
University of Virginia CS 655: Programming Languages |
uvacs655@egroups.com |