BNF for MackASM.jj

TOKENS

<DEFAULT> SKIP : {
" "
| "\t"
| "\n"
| "\r"
| <"//" (~["\n","\r"])* ("\n" | "\r" | "\r\n")>
| <"/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/">
}

   
<DEFAULT> 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"))* "\"">
}

   
<DEFAULT> 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: ":">
}

   
<DEFAULT> TOKEN : {
<IDENTIFIER: <LETTER> (<LETTER> | <DIGIT>)*>
| <#LETTER: ["$","A"-"Z","_","a"-"z"]>
| <#DIGIT: ["0"-"9"]>
}

   

NON-TERMINALS

MackASMdoc ::= ( ConstDef )* ( BssSectionDef )? ( DataSectionDef )? CodeSectionDef <EOF>
ConstDef ::= <IDENTIFIER> <CONST> Expr
Expr ::= term ( "+" Expr | "-" Expr )*
term ::= unary ( "*" term | "/" term )*
unary ::= "-" element
| element
element ::= <INTEGER_LITERAL>
| <IDENTIFIER>
| "(" Expr ")"
BssSectionDef ::= <START> <BSS_SEC> ( <SECTION> )? ( BssDef | ConstDef )*
BssDef ::= ( <IDENTIFIER> )? ( <DATA> ( <DOT_B> | <DOT_L> )? | <ARRAY> ( <DOT_B> | <DOT_L> )? "[" Expr "]" )
DataSectionDef ::= <START> <DATA_SEC> ( <SECTION> )? ( DataDef | ConstDef )*
DataDef ::= ( <IDENTIFIER> )? ( <DATA> ( <DOT_B> | <DOT_L> )? Expr | <ARRAY> ( <DOT_B> | <DOT_L> )? Expr "[" Expr "]" | <STRING> <STRING_LITERAL> )
CodeSectionDef ::= <START> <CODE_SEC> ( <SECTION> )? ( CodeDef | ConstDef )*
CodeDef ::= ( <IDENTIFIER> <COLON> )? ( <PUSH> <ARROW> <IDENTIFIER> LabelDistance | <PUSH> Expr | <POP> | <CLEAR> | <DUP> ( <DOT_NEG1> | Operands1 ) | <ADD> Operands2 | <SUB> Operands2 | <MUL> Operands2 | <DIV> Operands2 | <AND> Operands2 | <OR> Operands2 | <XOR> Operands2 | <ARSHIFT> Operands2 | <RSHIFT> Operands2 | <LSHIFT> Operands2 | <NOT> Operands1 | <NEG> Operands1 | <B> CondBranch | <RETURN> | <SYSCALL> Operands | <CALL> CondBranch | <LOAD> MemCompleters | <STORE> MemCompleters ( "," Expr )? )
CondBranch ::= ( <DOT_DNZ> Expr | <DOT_GT> Operands2 | <DOT_EQ> Operands2 | <DOT_GE> Operands2 | <DOT_LT> Operands2 | <DOT_NE> Operands2 | <DOT_LE> Operands2 )? ( <ARROW> <IDENTIFIER> LabelDistance )?
// Each ".far" after the label means another byte is needed to push the label.
LabelDistance ::= ( <DOT_FAR> )*
// MemCompleters() is used to LOAD and STORE stuff.  These instructions does not use Operands()
// because we do not want the variables to auto load. We just want their address pushed.
MemCompleters ::= ( <DOT_P> )? ( <DOT_B> | <DOT_L> )? ( Expr )?
// Any number of operands.
Operands ::= ( Operand ( "," Operand )* )?
// 0, 1, 2 or 3 operands.
Operands3 ::= ( Operand ( "," Operand ( "," Operand )? )? )?
// 0, 1 or 2 operands.
Operands2 ::= ( Operand ( "," Operand )? )?
// 0 or 1 operand.
Operands1 ::= ( 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.
Operand ::= Expr