The HackC Language Definition
Table of contents.
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
;
}
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