/**

 *

 * MackASM grammar defintion for use with JavaCC

 *

 **/

 

options { JDK_VERSION = "1.5"; }

 

PARSER_BEGIN( MackASM )

package parser;

import java.util.*;

import editor.Mack;

 

public class MackASM

{

  public static Mack  mack = null;

}

PARSER_END( MackASM )

 

SKIP : {

 " "

|  "\t"

|  "\n"

|  "\r"

|  <"//" (~["\n","\r"])* ("\n" | "\r" | "\r\n")>

|  <"/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/">

}

 

TOKEN : {

 <INTEGER_LITERAL: <DECIMAL_LITERAL> | <HEX_LITERAL> >

|  <#DECIMAL_LITERAL: ["0"-"9"] (["0"-"9"])*>

|  <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+>

|  <CHARACTER_LITERAL: "\'" (~["\'","\\","\n","\r"] | "\\" (["n","t","b","r","f","\\","\'","\""] | ["0"-"9"] (["0"-"9"])? | ["0"-"2"] ["0"-"9"] ["0"-"9"])) "\'">

|  <STRING_LITERAL: "\"" ( ~["\"","\\","\n","\r"] | "\\" ( ["n","t","b","r","f","\\","\'","\""] | ["0"-"9"] (["0"-"9"])?  | ["0"-"2"] ["0"-"9"] ["0"-"9"] | ( ["\n","\r"] | "\r\n")))* "\"">

}

 

TOKEN : {

<SYSCALL: "syscall">  |

<SECTION: "SECTION">  |

<ARSHIFT: "arshift">  |

<RETURN:  "return">   |

<RSHIFT:  "rshift">   |

<STRING:  "string">   |

<LSHIFT:  "lshift">   |

<CONST:   "const">    |

<CLEAR:   "clear">    |

<START:   "START">    |

<ARRAY:   "array">    |

<STORE:   "store">    |

<DOT_FAR: ".far">     |

<DATA_SEC:"DATA">     |

<DATA:    "data">     |

<CODE_SEC:"CODE">     |

<PUSH:    "push">     |

<CALL:    "call">     |

<LOAD:    "load">     |

<BSS_SEC: "BSS">      |

<DOT_DNZ: ".dnz">     |

<POP:     "pop">      |

<DUP:     "dup">      |

<ADD:     "add">      |

<SUB:     "sub">      |

<MUL:     "mul">      |

<DIV:     "div">      |

<AND:     "and">      |

<XOR:     "xor">      |

<NOT:     "not">      |

<NEG:     "neg">      |

<DOT_NEG1:".-1">      |

<DOT_LT:  ".<">       |

<DOT_LE:  ".<=">      |

<DOT_EQ:  ".=">       |

<DOT_NE:  ".<>">      |

<DOT_GE:  ".>=">      |

<DOT_GT:  ".>">       |

<ARROW:   "->">       |

<DOT_P:   ".p">       |

<DOT_B:   ".b">       |

<DOT_L:   ".l">       |

<OR:      "or">       |

<B:       "b">        |

<COLON:   ":">

}

 

TOKEN : {

 <IDENTIFIER: <LETTER> (<LETTER> | <DIGIT>)*>

|  <#LETTER: ["$","A"-"Z","_","a"-"z"]>

|  <#DIGIT: ["0"-"9"]>

}

 

void MackASMdoc( Mack  mackFile ) :             {mack = mackFile;}

{

  ( ConstDef() )*

  [ LOOKAHEAD(2) BssSectionDef() ]

  [ LOOKAHEAD(2) DataSectionDef() ]

  CodeSectionDef()

  < EOF >

}

 

 

void ConstDef() :                               {Token name; int  value;}

{

  name= <IDENTIFIER>  <CONST>  value= Expr()    { mack.defConst(name, value); }

}

 

int Expr():                                     { int  a; int  b; }

{

  a= term()

  (

  "+" b= Expr()                                 { a += b; }

  |

  "-" b= Expr()                                 { a -= b; }

  )*                                            { return a; }

}

int term():                                     { int  a; int  b; }

{

  a= unary()

  (

  "*" b= term()                                 { a *= b; }

  |

  "/" b= term()                                 { a /= b; }

  )*                                            { return a; }

}

int unary():                                    { int  a; }

{

  "-" a= element()                              { return -a; }

  |

  a= element()                                  { return a; }

}

int element():                                  { Token  tok; int  a; }

{

  tok= <INTEGER_LITERAL>                        { return mack.parseInt(tok); }

  |

  LOOKAHEAD( {getToken(1).kind==IDENTIFIER  &&  getToken(2).kind!=COLON} )

  tok= <IDENTIFIER>                             { return mack.ref(tok); }               

  |

  "(" a=Expr() ")"                              { return a; }

}

 

 

void BssSectionDef() : {}

{

  <START> <BSS_SEC> [ <SECTION> ]

  ( LOOKAHEAD(2) BssDef() | ConstDef() )*

}

 

 

void BssDef() :                                 { Token  name=null; int  size=2; int  initValue; int  repeat=1; }

{

  [ name= <IDENTIFIER> ]

 

  (

    <DATA>  [ <DOT_B> {size=1;} | <DOT_L> {size=4;} ]

    |

    <ARRAY> [ <DOT_B> {size=1;} | <DOT_L> {size=4;} ] "[" repeat= Expr() "]"

  )

                                                { mack.defBss(name, size, repeat); }

}

 

void DataSectionDef() : {}

{

  <START> <DATA_SEC> [ <SECTION> ]

  ( LOOKAHEAD(2) DataDef() | ConstDef() )*

}

 

 

void DataDef() :                                { Token  name=null; int  size=2; int  initValue; int  repeat=1; Token str; }

{

  [ name= <IDENTIFIER> ]

 

  (

    <DATA>  [ <DOT_B> {size=1;} | <DOT_L> {size=4;} ] initValue= Expr()                       { mack.defData(name, size, initValue, 1); }

    |

    <ARRAY> [ <DOT_B> {size=1;} | <DOT_L> {size=4;} ] initValue= Expr() "[" repeat= Expr() "]"{ mack.defData(name, size, initValue, repeat); }

    |

    <STRING> str=<STRING_LITERAL>                                                             { mack.defString(name, str); }

  )

                                                

}

 

 

void CodeSectionDef() : {}

{

  <START> <CODE_SEC> [ <SECTION> ]

  ( LOOKAHEAD(2) CodeDef() | ConstDef() )*

}

 

 

void CodeDef() :                                { Token  tok; int  value; int  sizeMask; mack.resetLoadSize(); }

{

  [ tok= <IDENTIFIER> <COLON>                   { mack.defLabel(tok); } ]

 

  ( LOOKAHEAD(2)

    <PUSH>  <ARROW> tok= <IDENTIFIER> value= LabelDistance() { mack.genPushLabel(tok,value); }

    |

    tok= <PUSH>   value= Expr()                 { mack.genPush(value); }

    |

    tok= <POP>                                  { mack.genOp(0xC0, tok, -1); }         

    |

    tok= <CLEAR>                                { mack.genOp(0xC1, tok, -999); }         

    |

    tok= <DUP> ( <DOT_NEG1> {mack.genOp(0xC3, tok, +1);} | Operands1() {mack.genOp(0xC2, tok, +1);} )                                  

    |

    tok= <ADD> Operands2()                       { mack.genOp(0xC4, tok, -1); }         

    |

    tok= <SUB> Operands2()                       { mack.genOp(0xC5, tok, -1); }         

    |

    tok= <MUL> Operands2()                       { mack.genOp(0xC6, tok, -1); }         

    |

    tok= <DIV> Operands2()                       { mack.genOp(0xC7, tok, -1); }         

    |

    tok= <AND> Operands2()                       { mack.genOp(0xC8, tok, -1); }         

    |

    tok= <OR> Operands2()                        { mack.genOp(0xC9, tok, -1); }         

    |

    tok= <XOR> Operands2()                       { mack.genOp(0xCA, tok, -1); }          

    |

    tok= <ARSHIFT> Operands2()                   { mack.genOp(0xCB, tok, -1); }         

    |

    tok= <RSHIFT> Operands2()                    { mack.genOp(0xCC, tok, -1); }         

    |

    tok= <LSHIFT> Operands2()                    { mack.genOp(0xCD, tok, -1); }         

    |

    tok= <NOT> Operands1()                       { mack.genOp(0xCE, tok, 0); }         

    |

    tok= <NEG> Operands1()                       { mack.genOp(0xCF, tok, 0); }         

    |

    tok= <B> CondBranch(0xD0, tok)

    |

    tok= <RETURN>                               { mack.genOp(0xD7, tok, -1); }         

    |

    tok= <SYSCALL> Operands()                   { mack.genOp(0xD8, tok, -999); }         

    |

    tok= <CALL> CondBranch(0xD8, tok)      

    |

    tok= <LOAD> sizeMask= MemCompleters()       { mack.genOp(0xE0 | sizeMask, tok, 0); }

    |

    tok= <STORE> sizeMask= MemCompleters() ["," value= Expr() {mack.genPush(value);} ]

                                                {mack.genOp(0xF0 | sizeMask, tok, -2); }

  )

}

 

 

void CondBranch( int  opCode, Token  tok ) :    { int  value; int  condCode=7; Token  labTok=null; int  howFar=0; }

{

  [

    LOOKAHEAD( {getToken(1).kind==DOT_DNZ  &&  token.kind==B} )

    <DOT_DNZ> value= Expr()                   { mack.genPush(value); condCode=0; }

    |

    <DOT_GT>  Operands2()                       { condCode=1; }

    |

    <DOT_EQ> Operands2()                        { condCode=2; }

    |

    <DOT_GE> Operands2()                        { condCode=3; }

    |

    <DOT_LT> Operands2()                        { condCode=4; }

    |

    <DOT_NE> Operands2()                        { condCode=5; }

    |

    <DOT_LE> Operands2()                        { condCode=6; }

  ]

  [

       <ARROW> labTok= <IDENTIFIER> howFar= LabelDistance()

  ]

                                                { mack.genBranch(opCode | condCode, tok, labTok, howFar); }

}

 

// Each ".far" after the label means another byte is needed to push the label.

int LabelDistance() :                               { int  howFar=0; }

{

  (

    <DOT_FAR>                                   { howFar++; }

  )*                                            { return howFar; }

}

 

 

// MemCompleters() is used to LOAD and STORE stuff.  These instructions do not use Operands()

// because we do not want the variables to auto load. We just want their address pushed.

int MemCompleters() : { int  value; int  mem=0; int  size=2; }

{

  [<DOT_P> {mem=0x04;}]

  [<DOT_B> {size=0x01;} | <DOT_L> {size=0x03;}]

  [LOOKAHEAD(Expr())

    value= Expr()                               { mack.genPush(value); }

  ]

                                                { return mem | size; }

                                                 

}

 

// Any number of operands.

void Operands() : {}

{

  [ LOOKAHEAD(1)

    Operand()  ( LOOKAHEAD(1) "," Operand() )*

  ]

}

// 0, 1, 2 or 3 operands.

void Operands3() : {}

{

  [ Operand() [ "," Operand() [ "," Operand() ] ] ]

}

// 0, 1 or 2 operands.

void Operands2() : {}

{

  [ LOOKAHEAD(1)

    Operand() [ "," Operand() ]

  ]

}

// 0 or 1 operand.

void Operands1() : {}

{

  [ LOOKAHEAD(1)

    Operand()

  ]

}

 

// When an Expression sees a variable, it sets a global called "loadSize".

// If loadSize is set, this assumes you want to do a load, else it just pushes the value.

void Operand() :                                { int value; mack.resetLoadSize(); }

{

  value= Expr()                                                      { mack.genPushOrLoad(value); }

}