The HackC Language Definition

Table of contents.

Syntax Extension

The following code is actual HackC code, used to generate the HackC parser. It is not only source, but a formal definition of the HackC core syntax.

This code illustrates the simplicity with which HackC syntax can be extended. Both the syntax, and parse tree structure are defined together. Both flex and bison files are generated from this format.

syntax {

globalDeclarations: /* Empty */ -> ()
| globalDeclarations globalDeclaration -> $1.$2
;

globalDeclaration: parseRules
;

parseRules: "syntax" "\{" rules "\}" -> "syntax"{$3}
;

rules: /* Empty */ -> ()
| rules rule -> $1.$2
;

rule: IDENTIFIER ":" ruleExpression ";" -> $1{$3}
;

ruleExpression: patterns
;

patterns: pattern -> ($1)
| patterns "\|" pattern -> $1.$3
;

pattern: elements "->" listExpression -> ($1 $3)
| elements
;

elements: /* Empty */ -> ()
| elements element -> $1.$2
;

element: IDENTIFIER
| STRING
;

listExpression: catListExpression
;

catListExpression: basicListExpression
| catListExpression "\." basicListExpression -> "catLists"{($1 $3)}
;

basicListExpression: setAttom
| buildList
| constListExpression
;

constListExpression: positionalParameter
| STRING
| "true" -> true
| "false" -> false
;

setAttom: constListExpression "\{" listExpression "\}" -> "setAtom"{($3 $1)}
;

buildList: "\(" listExpressions "\)" -> $2
| "\(" "\)" -> ()
;

listExpressions: listExpression -> ($1)
| listExpressions listExpression -> $1.$2
;

positionalParameter: "\$" INTEGER -> $2
;

}

Core Language

Here starts the initial syntax of the HackC language proper. It's mostly a subset of C. It's meant to be simple, as HackC is extensible.

syntax {

globalDeclaration: moduleDeclaration
| enumDeclaration
| function
| classDeclaration
| includeDeclaration ";"
| exportableVariableDeclaration ";"
;

moduleDeclaration: optExtern "module" IDENTIFIER ";" -> "module"{($3 $1)}
;

optExtern: /* Empty */ -> true
| "extern" -> false
;

includeDeclaration: "include" includedModules -> "include"{$2}
;

includedModules: includedModule -> ($1)
| includedModules "," includedModule -> $1.$3
;

includedModule: IDENTIFIER
;

enumDeclaration: optExport "enum" IDENTIFIER "{" entries "}" -> "enum"{($3 $1 $5)}
;

optExport: /* Empty */ -> false
| "export" -> true
;

entries: entry -> ($1)
| entries "," entry -> $1.$3
;

entry: IDENTIFIER
;

function: functionType "\(" parameters "\)" "\{" statements "\}" -> "function"{$1.$3.$6}
;

functionType: exportableType IDENTIFIER -> ($2 $1)
| IDENTIFIER -> ($1 (false))
| "export" IDENTIFIER -> ($2 (true))
;

parameters: /* Empty */ -> ()
| oneOrMoreParameters
| oneOrMoreParameters lastParameter -> $1.$2
;

oneOrMoreParameters: parameter -> ($1)
| oneOrMoreParameters "," parameter -> $1.$3
;

lastParameter: parameter
| variable "\.\.\." -> "..."{($1)}
;

parameter: "out" type variable -> "out"{($2 $3)}
| type variable -> "in"{($1 $2)}
;

block: "\{" statements "\}" -> $2
;

statements: /* Empty */ -> ()
| statements statement -> $1.$2
;

statement: localVariableDeclaration ";"
| assignmentStatement ";"
| ifStatement
| doWhileStatement
| forStatement
| switchStatement
| functionCallStatement ";"
| returnStatement ";"
| newStatement ";"
| deleteStatement ";"
| namespaceStatement
;

exportableVariableDeclaration: exportableType variables -> "varDecl"{($1 $2)}
;

localVariableDeclaration: type initializableVariables -> "varDecl"{($1 $2)}
;

exportableType: type -> ($1 false)
| "export" type -> ($2 true)
;

type: name
| "string"
| "char"
| "int[0-9]*"
| "uint[0-9]*"
| "float"
| "double"
| "bool"
;

initializableVariables: initializableVariable -> ($1)
| initializableVariables "," initializableVariable -> $1.$3
;

initializableVariable: variable "=" expression -> "initialize"{($1 $3)}
| variable
;

variables: variable -> ($1)
| variables "," variable -> $1.$3
;

variable: IDENTIFIER
;

assignmentStatement: name assignmentOperator expression -> "assign"{($1 $2 $3)}
;

assignmentOperator: "="
;

name: IDENTIFIER -> ($1)
| name "\." IDENTIFIER -> $1.$2
;

ifStatement: "if" expression block elsePart -> "if"{($1 $2 $3)}
;

elsePart: /* Empty */ -> ()
| "else" block -> $2
| "else" ifStatement -> $2
;

doWhileStatement: "do" block "while" expression ";" -> "doWhile"{($2 $4 ())}
| "do" block "while" expression block -> "doWhile"{($2 $3 $4)}
| "while" expression block -> "doWhile"{(() $2 $3)}
;

forStatement: "for" "\(" assignmentStatement "," expression "," assignmentStatement "\)" block
-> "for"{($3 $5 $7 $9)}
;

switchStatement: "switch" expression "\{" caseBlocks optDefaultCase "\}" -> "switch"{($2 $4 $5)}
;

caseBlocks: /* Empty */ -> ()
| caseBlocks caseBlock -> $1.$2
;

caseBlock: cases oneOrMoreStatements -> "caseBlock"{($1 $2)}
;

cases: "case" expression ":" -> ($2)
| cases "case" expression ":" -> $1.$2
;

oneOrMoreStatements: statement -> ($1)
| oneOrMoreStatements statement -> $1.$2
;

optDefaultCase: /* Empty */ -> ()
| "default" ":" statements -> "default"{$3}
;

functionCallStatement: functionCall
;

functionCall: name "\(" expressions "\)" -> "functionCall"{($1 $3)}
;

expressions: /* Empty */ -> ()
| oneOrMoreExpressions
;

oneOrMoreExpressions: expression -> ($1)
| oneOrMoreExpressions "," expression -> $1.$3
;

returnStatement: "return"
| "return" expression -> "return"{($2)}
;

newStatement: "new" name -> "new"{$2}
;

deleteStatement: "delete" name -> "delete"{$2}
;

namespaceStatement: block -> "namespace"{$1}
;

classDeclaration: optExport "class" IDENTIFIER optBaseClass "\{" fieldDeclarations "\}"
-> "class"{($3 $1 $4 $6)}
;

optBaseClass: /* Empty */ -> ()
| ":" name -> $2
;

fieldDeclarations: /* empty */ -> ()
| fieldDeclarations fieldDeclaration -> $1.$2
;

fieldDeclaration: exportableVariableDeclaration ";"
;

expression: conditionalExpression
;

conditionalExpression: orExpression
| orExpression "\?" expression ":" conditionalExpression -> "?:"{($1 $3 $5)}
;

orExpression: andExpression
| andExpression "\|\|" andExpression -> $2{($1 $3)}
;

andExpression: bitOrExpression
| bitOrExpression "\&\&" bitOrExpression -> $2{($1 $3)}
;

bitOrExpression: bitXorExpression
| bitXorExpression "\|" bitXorExpression -> $2{($1 $3)}
;

bitXorExpression: bitAndExpression
| bitAndExpression "\^" bitAndExpression -> $2{($1 $3)}
;

bitAndExpression: equalExpression
| equalExpression "\&" equalExpression -> $2{($1 $3)}
;

equalExpression: relExpression
| relExpression "==" relExpression -> $2{($1 $3)}
| relExpression "!=" relExpression -> $2{($1 $3)}
;

relExpression: shiftExpression
| shiftExpression "\<" shiftExpression -> $2{($1 $3)}
| shiftExpression "\<=" shiftExpression -> $2{($1 $3)}
| shiftExpression "\>" shiftExpression -> $2{($1 $3)}
| shiftExpression "\>=" shiftExpression -> $2{($1 $3)}
;

shiftExpression: addExpression
| addExpression "\<\<" addExpression -> $2{($1 $3)}
| addExpression "\>\>" addExpression -> $2{($1 $3)}
;

addExpression: mulExpression
| mulExpression "\+" mulExpression -> $2{($1 $3)}
| mulExpression "-" mulExpression -> $2{($1 $3)}
;

mulExpression: unaryExpression
| unaryExpression "\*" unaryExpression -> $2{($1 $3)}
| unaryExpression "\/" unaryExpression -> $2{($1 $3)}
| unaryExpression "%" unaryExpression -> $2{($1 $3)}
;

unaryExpression: postfixExpression
| "-" unaryExpression -> $1{($2)}
| "\+" unaryExpression -> $1{($2)}
| "!" unaryExpression -> $1{($2)}
| "~" unaryExpression -> $1{($2)}
| "new" unaryExpression -> $1{($2)}
;

postfixExpression: primaryExpression
| functionCall
| postfixExpression "\[" expression "\]" -> "[]"{($1 $3)}
;

primaryExpression: name
| "null"
| "true" -> true
| "false" -> false
| numericLiteral
| STRING
;

numericLiteral: INTEGER
| DOUBLE
;

}

Last changed: 04/06/2003, 13:07:48