cimple-0.0.4: src/Language/Cimple/Parser.y
{
module Language.Cimple.Parser
( parseTranslationUnit
) where
import Language.Cimple.AST (AssignOp (..), BinaryOp (..),
CommentStyle (..), LiteralType (..),
Node (..), Scope (..), UnaryOp (..))
import Language.Cimple.Lexer (Alex, AlexPosn (..), Lexeme (..),
alexError, alexMonadScan)
import Language.Cimple.Tokens (LexemeClass (..))
}
-- Conflict between (static) FunctionDecl and (static) ConstDecl.
%expect 2
%name parseTranslationUnit TranslationUnit
%error {parseError}
%errorhandlertype explist
%lexer {lexwrap} {L _ Eof _}
%monad {Alex}
%tokentype {Lexeme String}
%token
ID_CONST { L _ IdConst _ }
ID_FUNC_TYPE { L _ IdFuncType _ }
ID_STD_TYPE { L _ IdStdType _ }
ID_SUE_TYPE { L _ IdSueType _ }
ID_TYVAR { L _ IdTyVar _ }
ID_VAR { L _ IdVar _ }
bitmask { L _ KwBitmask _ }
break { L _ KwBreak _ }
case { L _ KwCase _ }
class { L _ KwClass _ }
const { L _ KwConst _ }
continue { L _ KwContinue _ }
default { L _ KwDefault _ }
do { L _ KwDo _ }
else { L _ KwElse _ }
enum { L _ KwEnum _ }
'error' { L _ KwError _ }
event { L _ KwEvent _ }
extern { L _ KwExtern _ }
for { L _ KwFor _ }
goto { L _ KwGoto _ }
if { L _ KwIf _ }
namespace { L _ KwNamespace _ }
return { L _ KwReturn _ }
sizeof { L _ KwSizeof _ }
static { L _ KwStatic _ }
static_assert { L _ KwStaticAssert _ }
struct { L _ KwStruct _ }
switch { L _ KwSwitch _ }
this { L _ KwThis _ }
typedef { L _ KwTypedef _ }
union { L _ KwUnion _ }
VLA { L _ KwVla _ }
void { L _ KwVoid _ }
while { L _ KwWhile _ }
with { L _ KwWith _ }
LIT_CHAR { L _ LitChar _ }
LIT_FALSE { L _ LitFalse _ }
LIT_TRUE { L _ LitTrue _ }
LIT_INTEGER { L _ LitInteger _ }
LIT_STRING { L _ LitString _ }
LIT_SYS_INCLUDE { L _ LitSysInclude _ }
'&' { L _ PctAmpersand _ }
'&&' { L _ PctAmpersandAmpersand _ }
'&=' { L _ PctAmpersandEq _ }
'->' { L _ PctArrow _ }
'*' { L _ PctAsterisk _ }
'*=' { L _ PctAsteriskEq _ }
'^' { L _ PctCaret _ }
'^=' { L _ PctCaretEq _ }
':' { L _ PctColon _ }
',' { L _ PctComma _ }
'!' { L _ PctEMark _ }
'!=' { L _ PctEMarkEq _ }
'=' { L _ PctEq _ }
'==' { L _ PctEqEq _ }
'>' { L _ PctGreater _ }
'>=' { L _ PctGreaterEq _ }
'>>' { L _ PctGreaterGreater _ }
'>>=' { L _ PctGreaterGreaterEq _ }
'{' { L _ PctLBrace _ }
'[' { L _ PctLBrack _ }
'<' { L _ PctLess _ }
'<=' { L _ PctLessEq _ }
'<<' { L _ PctLessLess _ }
'<<=' { L _ PctLessLessEq _ }
'(' { L _ PctLParen _ }
'-' { L _ PctMinus _ }
'-=' { L _ PctMinusEq _ }
'--' { L _ PctMinusMinus _ }
'%' { L _ PctPercent _ }
'%=' { L _ PctPercentEq _ }
'.' { L _ PctPeriod _ }
'...' { L _ PctEllipsis _ }
'|' { L _ PctPipe _ }
'|=' { L _ PctPipeEq _ }
'||' { L _ PctPipePipe _ }
'+' { L _ PctPlus _ }
'+=' { L _ PctPlusEq _ }
'++' { L _ PctPlusPlus _ }
'?' { L _ PctQMark _ }
'}' { L _ PctRBrace _ }
']' { L _ PctRBrack _ }
')' { L _ PctRParen _ }
';' { L _ PctSemicolon _ }
'/' { L _ PctSlash _ }
'/=' { L _ PctSlashEq _ }
'~' { L _ PctTilde _ }
'defined' { L _ PpDefined _ }
'#define' { L _ PpDefine _ }
'#elif' { L _ PpElif _ }
'#else' { L _ PpElse _ }
'#endif' { L _ PpEndif _ }
'#if' { L _ PpIf _ }
'#ifdef' { L _ PpIfdef _ }
'#ifndef' { L _ PpIfndef _ }
'#include' { L _ PpInclude _ }
'#undef' { L _ PpUndef _ }
'\n' { L _ PpNewline _ }
'/**/' { L _ CmtBlock _ }
'/*' { L _ CmtStart _ }
'/**' { L _ CmtStartDoc _ }
'/***' { L _ CmtStartBlock _ }
' * ' { L _ CmtIndent _ }
'*/' { L _ CmtEnd _ }
'Copyright' { L _ CmtSpdxCopyright _ }
'License' { L _ CmtSpdxLicense _ }
CMT_CODE { L _ CmtCode _ }
CMT_WORD { L _ CmtWord _ }
CMT_REF { L _ CmtRef _ }
%left ','
%right '=' '+=' '-=' '*=' '/=' '%=' '<<=' '>>=' '&=' '^=' '|='
%right '?' ':'
%left '||'
%left '&&'
%left '|'
%left '^'
%left '&'
%left '!=' '=='
%left '<' '<=' '>' '>='
%left '<<' '>>'
%left '+' '-'
%left '*' '/' '%'
%right CAST ADDRESS NEG DEREF sizeof '!' '~' '++' '--'
%left '->' '.' '(' '['
%%
TranslationUnit :: { [StringNode] }
TranslationUnit
: ToplevelDecls { reverse $1 }
| LicenseDecl ToplevelDecls { $1 : reverse $2 }
LicenseDecl :: { StringNode }
LicenseDecl
: '/*' 'License' CMT_WORD '\n' CopyrightDecls '*/' { LicenseDecl $3 $5 }
CopyrightDecls :: { [StringNode] }
CopyrightDecls
: CopyrightDecl { [$1] }
| CopyrightDecls CopyrightDecl { $2 : $1 }
CopyrightDecl :: { StringNode }
CopyrightDecl
: ' * ' 'Copyright' CopyrightDates CopyrightOwner '\n' { CopyrightDecl (fst $3) (snd $3) $4 }
CopyrightDates :: { (StringLexeme, Maybe StringLexeme) }
CopyrightDates
: LIT_INTEGER { ($1, Nothing) }
| LIT_INTEGER '-' LIT_INTEGER { ($1, Just $3) }
CopyrightOwner :: { [StringLexeme] }
CopyrightOwner
: CMT_WORD CommentWords { $1 : reverse $2 }
ToplevelDecls :: { [StringNode] }
ToplevelDecls
: ToplevelDecl { [$1] }
| ToplevelDecls ToplevelDecl { $2 : $1 }
ToplevelDecl :: { StringNode }
ToplevelDecl
: AggregateDecl { $1 }
| Comment { $1 }
| ConstDecl { $1 }
| EnumDecl { $1 }
| ErrorDecl { $1 }
| Event { $1 }
| ExternC { $1 }
| FunctionDecl { $1 }
| Namespace { $1 }
| PreprocDefine { $1 }
| PreprocIfdef(ToplevelDecls) { $1 }
| PreprocIf(ToplevelDecls) { $1 }
| PreprocInclude { $1 }
| PreprocUndef { $1 }
| StaticAssert { $1 }
| TypedefDecl { $1 }
StaticAssert :: { StringNode }
StaticAssert
: static_assert '(' ConstExpr ',' LIT_STRING ')' ';' { StaticAssert $3 $5 }
Namespace :: { StringNode }
Namespace
: NamespaceDeclarator { $1 Global }
| static NamespaceDeclarator { $2 Static }
NamespaceDeclarator :: { Scope -> StringNode }
NamespaceDeclarator
: class ID_SUE_TYPE TypeParams '{' ToplevelDecls '}' { \s -> Class s $2 $3 (reverse $5) }
| namespace IdVar '{' ToplevelDecls '}' { \s -> Namespace s $2 (reverse $4) }
TypeParams :: { [StringNode] }
TypeParams
: { [] }
| '<' ID_TYVAR '>' { [TyVar $2] }
Event :: { StringNode }
Event
: event IdVar '{' Comment EventType '}' { Event $2 (Commented $4 $5) }
| event IdVar const '{' Comment EventType '}' { Event $2 (Commented $5 $6) }
EventType :: { StringNode }
EventType
: typedef void EventParams ';' { $3 }
EventParams :: { StringNode }
EventParams
: FunctionParamList { EventParams $1 }
ErrorDecl :: { StringNode }
ErrorDecl
: 'error' for IdVar EnumeratorList { ErrorDecl $3 $4 }
Comment :: { StringNode }
Comment
: '/*' CommentTokens '*/' { Comment Regular $1 (reverse $2) $3 }
| '/**' CommentTokens '*/' { Comment Doxygen $1 (reverse $2) $3 }
| '/***' CommentTokens '*/' { Comment Block $1 (reverse $2) $3 }
| '/**/' { CommentBlock $1 }
CommentTokens :: { [StringNode] }
CommentTokens
: CommentToken { [$1] }
| CommentTokens CommentToken { $2 : $1 }
CommentToken :: { StringNode }
CommentToken
: CommentWord { CommentWord $1 }
| '\n' { CommentWord $1 }
| ' * ' { CommentWord $1 }
CommentWords :: { [StringLexeme] }
CommentWords
: { [] }
| CommentWords CommentWord { $2 : $1 }
CommentWord :: { StringLexeme }
CommentWord
: CMT_WORD { $1 }
| CMT_REF { $1 }
| CMT_CODE { $1 }
| LIT_INTEGER { $1 }
| LIT_STRING { $1 }
| '.' { $1 }
| '?' { $1 }
| '!' { $1 }
| ',' { $1 }
| ';' { $1 }
| ':' { $1 }
| '(' { $1 }
| ')' { $1 }
| '<' { $1 }
| '>' { $1 }
| '/' { $1 }
| '+' { $1 }
| '-' { $1 }
| '=' { $1 }
PreprocIfdef(decls)
: '#ifdef' ID_CONST decls PreprocElse(decls) '#endif' { PreprocIfdef $2 (reverse $3) $4 }
| '#ifndef' ID_CONST decls PreprocElse(decls) '#endif' { PreprocIfndef $2 (reverse $3) $4 }
PreprocIf(decls)
: '#if' PreprocConstExpr '\n' decls PreprocElse(decls) '#endif' { PreprocIf $2 (reverse $4) $5 }
PreprocElse(decls)
: { PreprocElse [] }
| '#else' decls { PreprocElse $2 }
| '#elif' PreprocConstExpr '\n' decls PreprocElse(decls) { PreprocElif $2 (reverse $4) $5 }
PreprocInclude :: { StringNode }
PreprocInclude
: '#include' LIT_STRING { PreprocInclude $2 }
| '#include' LIT_SYS_INCLUDE { PreprocInclude $2 }
PreprocDefine :: { StringNode }
PreprocDefine
: '#define' ID_CONST '\n' { PreprocDefine $2 }
| '#define' ID_CONST PreprocSafeExpr(ConstExpr) '\n' { PreprocDefineConst $2 $3 }
| '#define' ID_CONST MacroParamList MacroBody '\n' { PreprocDefineMacro $2 $3 $4 }
PreprocUndef :: { StringNode }
PreprocUndef
: '#undef' ID_CONST { PreprocUndef $2 }
PreprocConstExpr :: { StringNode }
PreprocConstExpr
: PureExpr(PreprocConstExpr) { $1 }
| 'defined' '(' ID_CONST ')' { PreprocDefined $3 }
MacroParamList :: { [StringNode] }
MacroParamList
: '(' ')' { [] }
| '(' MacroParams ')' { reverse $2 }
| '(' MacroParams ',' '...' ')' { reverse $ Ellipsis : $2 }
MacroParams :: { [StringNode] }
MacroParams
: MacroParam { [$1] }
| MacroParams ',' MacroParam { $3 : $1 }
MacroParam :: { StringNode }
MacroParam
: IdVar { MacroParam $1 }
MacroBody :: { StringNode }
MacroBody
: do CompoundStmt while '(' LIT_INTEGER ')' {% macroBodyStmt $2 $5 }
| FunctionCall { MacroBodyFunCall $1 }
ExternC :: { StringNode }
ExternC
: '#ifdef' ID_CONST
extern LIT_STRING '{'
'#endif'
ToplevelDecls
'#ifdef' ID_CONST
'}'
'#endif' {% externC $2 $4 (reverse $7) $9 }
Stmts :: { [StringNode] }
Stmts
: Stmt { [$1] }
| Stmts Stmt { $2 : $1 }
Stmt :: { StringNode }
Stmt
: PreprocIfdef(Stmts) { $1 }
| PreprocIf(Stmts) { $1 }
| PreprocDefine Stmts PreprocUndef { PreprocScopedDefine $1 $2 $3 }
| LabelStmt { $1 }
| DeclStmt { $1 }
| CompoundStmt { CompoundStmt $1 }
| IfStmt { $1 }
| ForStmt { $1 }
| WhileStmt { $1 }
| DoWhileStmt { $1 }
| AssignExpr ';' { $1 }
| ExprStmt ';' { $1 }
| FunctionCall ';' { $1 }
| break ';' { Break }
| goto ID_CONST ';' { Goto $2 }
| continue ';' { Continue }
| return ';' { Return Nothing }
| return Expr ';' { Return (Just $2) }
| switch '(' Expr ')' CompoundStmt { SwitchStmt $3 $5 }
| Comment { $1 }
IfStmt :: { StringNode }
IfStmt
: if '(' Expr ')' CompoundStmt { IfStmt $3 $5 Nothing }
| if '(' Expr ')' CompoundStmt else IfStmt { IfStmt $3 $5 (Just $7) }
| if '(' Expr ')' CompoundStmt else CompoundStmt { IfStmt $3 $5 (Just (CompoundStmt $7)) }
ForStmt :: { StringNode }
ForStmt
: for '(' ForInit Expr ';' ForNext ')' CompoundStmt { ForStmt $3 $4 $6 $8 }
ForInit :: { StringNode }
ForInit
: AssignExpr ';' { $1 }
| VarDecl { $1 }
ForNext :: { StringNode }
ForNext
: ExprStmt { $1 }
| AssignExpr { $1 }
WhileStmt :: { StringNode }
WhileStmt
: while '(' Expr ')' CompoundStmt { WhileStmt $3 $5 }
DoWhileStmt :: { StringNode }
DoWhileStmt
: do CompoundStmt while '(' Expr ')' ';' { DoWhileStmt $2 $5 }
LabelStmt :: { StringNode }
LabelStmt
: case Expr ':' AfterLabelStmt { Case $2 $4 }
| default ':' AfterLabelStmt { Default $3 }
| ID_CONST ':' Stmt { Label $1 $3 }
AfterLabelStmt :: { StringNode }
AfterLabelStmt
: CompoundStmt { CompoundStmt $1 }
| LabelStmt { $1 }
| return Expr ';' { Return (Just $2) }
DeclStmt :: { StringNode }
DeclStmt
: VarDecl { $1 }
| VLA '(' QualType ',' IdVar ',' Expr ')' ';' { VLA $3 $5 $7 }
VarDecl :: { StringNode }
VarDecl
: QualType Declarator ';' { VarDecl $1 $2 }
Declarator :: { StringNode }
Declarator
: DeclSpec '=' InitialiserExpr { Declarator $1 (Just $3) }
| DeclSpec { Declarator $1 Nothing }
InitialiserExpr :: { StringNode }
InitialiserExpr
: InitialiserList { InitialiserList $1 }
| Expr { $1 }
DeclSpec :: { StringNode }
DeclSpec
: IdVar { DeclSpecVar $1 }
| DeclSpec '[' ']' { DeclSpecArray $1 Nothing }
| DeclSpec '[' Expr ']' { DeclSpecArray $1 (Just $3) }
IdVar :: { Lexeme String }
IdVar
: ID_VAR { $1 }
| default { $1 }
| 'error' { $1 }
InitialiserList :: { [StringNode] }
InitialiserList
: '{' Initialisers '}' { reverse $2 }
| '{' Initialisers ',' '}' { reverse $2 }
Initialisers :: { [StringNode] }
Initialisers
: Initialiser { [$1] }
| Initialisers ',' Initialiser { $3 : $1 }
Initialiser :: { StringNode }
Initialiser
: Expr { $1 }
| InitialiserList { InitialiserList $1 }
CompoundStmt :: { [StringNode] }
CompoundStmt
: '{' Stmts '}' { reverse $2 }
-- Expressions that are safe for use as macro body without () around it..
PreprocSafeExpr(x)
: LiteralExpr { $1 }
| '(' x ')' { ParenExpr $2 }
| '(' QualType ')' x %prec CAST { CastExpr $2 $4 }
| sizeof '(' x ')' { SizeofExpr $3 }
| sizeof '(' QualType ')' { SizeofType $3 }
ConstExpr :: { StringNode }
ConstExpr
: PureExpr(ConstExpr) { $1 }
PureExpr(x)
: PreprocSafeExpr(x) { $1 }
| x '!=' x { BinaryExpr $1 BopNe $3 }
| x '==' x { BinaryExpr $1 BopEq $3 }
| x '||' x { BinaryExpr $1 BopOr $3 }
| x '^' x { BinaryExpr $1 BopBitXor $3 }
| x '|' x { BinaryExpr $1 BopBitOr $3 }
| x '&&' x { BinaryExpr $1 BopAnd $3 }
| x '&' x { BinaryExpr $1 BopBitAnd $3 }
| x '/' x { BinaryExpr $1 BopDiv $3 }
| x '*' x { BinaryExpr $1 BopMul $3 }
| x '%' x { BinaryExpr $1 BopMod $3 }
| x '+' x { BinaryExpr $1 BopPlus $3 }
| x '-' x { BinaryExpr $1 BopMinus $3 }
| x '<' x { BinaryExpr $1 BopLt $3 }
| x '<=' x { BinaryExpr $1 BopLe $3 }
| x '<<' x { BinaryExpr $1 BopLsh $3 }
| x '>' x { BinaryExpr $1 BopGt $3 }
| x '>=' x { BinaryExpr $1 BopGe $3 }
| x '>>' x { BinaryExpr $1 BopRsh $3 }
| x '?' x ':' x { TernaryExpr $1 $3 $5 }
| '!' x { UnaryExpr UopNot $2 }
| '~' x { UnaryExpr UopNeg $2 }
| '-' x %prec NEG { UnaryExpr UopMinus $2 }
| '&' x %prec ADDRESS { UnaryExpr UopAddress $2 }
LiteralExpr :: { StringNode }
LiteralExpr
: StringLiteralExpr { $1 }
| LIT_CHAR { LiteralExpr Char $1 }
| LIT_INTEGER { LiteralExpr Int $1 }
| LIT_FALSE { LiteralExpr Bool $1 }
| LIT_TRUE { LiteralExpr Bool $1 }
| ID_CONST { LiteralExpr ConstId $1 }
StringLiteralExpr :: { StringNode }
StringLiteralExpr
: LIT_STRING { LiteralExpr String $1 }
| StringLiteralExpr LIT_STRING { $1 }
LhsExpr :: { StringNode }
LhsExpr
: IdVar { VarExpr $1 }
| '*' LhsExpr %prec DEREF { UnaryExpr UopDeref $2 }
| LhsExpr '.' IdVar { MemberAccess $1 $3 }
| LhsExpr '->' IdVar { PointerAccess $1 $3 }
| LhsExpr '[' Expr ']' { ArrayAccess $1 $3 }
Expr :: { StringNode }
Expr
: LhsExpr { $1 }
| ExprStmt { $1 }
| FunctionCall { $1 }
| CompoundExpr { $1 }
| PureExpr(Expr) { $1 }
-- Allow `(Type){0}` to set struct values to all-zero.
CompoundExpr :: { StringNode }
CompoundExpr
: '(' QualType ')' '{' Expr '}' { CompoundExpr $2 $5 }
AssignExpr :: { StringNode }
AssignExpr
: LhsExpr AssignOperator Expr { AssignExpr $1 $2 $3 }
AssignOperator :: { AssignOp }
AssignOperator
: '=' { AopEq }
| '*=' { AopMul }
| '/=' { AopDiv }
| '+=' { AopPlus }
| '-=' { AopMinus }
| '&=' { AopBitAnd }
| '|=' { AopBitOr }
| '^=' { AopBitXor }
| '%=' { AopMod }
| '<<=' { AopLsh }
| '>>=' { AopRsh }
ExprStmt :: { StringNode }
ExprStmt
: '++' Expr { UnaryExpr UopIncr $2 }
| '--' Expr { UnaryExpr UopDecr $2 }
FunctionCall :: { StringNode }
FunctionCall
: Expr ArgList { FunctionCall $1 $2 }
ArgList :: { [StringNode] }
ArgList
: '(' ')' { [] }
| '(' Args ')' { reverse $2 }
Args :: { [StringNode] }
Args
: Arg { [$1] }
| Args ',' Arg { $3 : $1 }
Arg :: { StringNode }
Arg
: Expr { $1 }
| Comment Expr { CommentExpr $1 $2 }
EnumDecl :: { StringNode }
EnumDecl
: enum class ID_SUE_TYPE EnumeratorList { EnumClass $3 $4 }
| enum ID_SUE_TYPE EnumeratorList ';' { EnumConsts (Just $2) $3 }
| enum EnumeratorList ';' { EnumConsts Nothing $2 }
| typedef enum ID_SUE_TYPE EnumeratorList ID_SUE_TYPE ';' { EnumDecl $3 $4 $5 }
| bitmask ID_SUE_TYPE EnumeratorList { EnumDecl $2 $3 $2 }
EnumeratorList :: { [StringNode] }
EnumeratorList
: '{' Enumerators '}' { reverse $2 }
Enumerators :: { [StringNode] }
Enumerators
: Enumerator { [$1] }
| Enumerators Enumerator { $2 : $1 }
Enumerator :: { StringNode }
Enumerator
: EnumeratorName ',' { Enumerator $1 Nothing }
| EnumeratorName '=' ConstExpr ',' { Enumerator $1 (Just $3) }
| namespace ID_CONST '{' Enumerators '}' { Namespace Global $2 $4 }
| Comment { $1 }
EnumeratorName :: { Lexeme String }
EnumeratorName
: ID_CONST { $1 }
| ID_SUE_TYPE { $1 }
AggregateDecl :: { StringNode }
AggregateDecl
: AggregateType ';' { $1 }
| class ID_SUE_TYPE TypeParams ';' { ClassForward $2 $3 }
| typedef AggregateType ID_SUE_TYPE ';' { Typedef $2 $3 }
AggregateType :: { StringNode }
AggregateType
: struct ID_SUE_TYPE '{' MemberDeclList '}' { Struct $2 $4 }
| struct this '{' MemberDeclList '}' { Struct $2 $4 }
| union ID_SUE_TYPE '{' MemberDeclList '}' { Union $2 $4 }
MemberDeclList :: { [StringNode] }
MemberDeclList
: MemberDecls { reverse $1 }
MemberDecls :: { [StringNode] }
MemberDecls
: MemberDecl { [$1] }
| MemberDecls MemberDecl { $2 : $1 }
MemberDecl :: { StringNode }
MemberDecl
: QualType DeclSpec ';' { MemberDecl $1 $2 Nothing }
| QualType DeclSpec ':' LIT_INTEGER ';' { MemberDecl $1 $2 (Just $4) }
| namespace IdVar '{' MemberDeclList '}' { Namespace Global $2 $4 }
| PreprocIfdef(MemberDeclList) { $1 }
| Comment { $1 }
TypedefDecl :: { StringNode }
TypedefDecl
: typedef QualType ID_SUE_TYPE ';' { Typedef $2 $3 }
| typedef FunctionPrototype(ID_FUNC_TYPE) ';' { TypedefFunction $2 }
QualType :: { StringNode }
QualType
: LeafType { $1 }
| LeafType '*' { TyPointer $1 }
| LeafType '*' '*' { TyPointer (TyPointer $1) }
| LeafType '*' const { TyConst (TyPointer $1) }
| LeafType '*' const '*' { TyPointer (TyConst (TyPointer $1)) }
| LeafType const { TyConst $1 }
| LeafType const '*' { TyPointer (TyConst $1) }
| LeafType const '*' const { TyConst (TyPointer (TyConst $1)) }
| LeafType const '*' const '*' { TyPointer (TyConst (TyPointer (TyConst $1))) }
| const LeafType { TyConst $2 }
| const LeafType '*' { TyPointer (TyConst $2) }
| const LeafType '*' const { TyConst (TyPointer (TyConst $2)) }
| const LeafType '*' const '*' { TyPointer (TyConst (TyPointer (TyConst $2))) }
LeafType :: { StringNode }
LeafType
: struct ID_SUE_TYPE { TyStruct $2 }
| void { TyStd $1 }
| this { TyStd $1 }
| ID_FUNC_TYPE { TyFunc $1 }
| ID_STD_TYPE { TyStd $1 }
| ID_SUE_TYPE { TyUserDefined $1 }
| ID_TYVAR { TyVar $1 }
FunctionDecl :: { StringNode }
FunctionDecl
: FunctionDeclarator { $1 Global }
| static FunctionDeclarator { $2 Static }
FunctionDeclarator :: { Scope -> StringNode }
FunctionDeclarator
: FunctionPrototype(IdVar) WithError { \s -> FunctionDecl s $1 $2 }
| FunctionPrototype(IdVar) CompoundStmt { \s -> FunctionDefn s $1 $2 }
| QualType DeclSpec '{' Accessors '}' { \s -> Property $1 $2 (reverse $4) }
Accessors :: { [StringNode] }
Accessors
: Accessor { [$1] }
| Accessors Accessor { $2 : $1 }
Accessor :: { StringNode }
Accessor
: IdVar FunctionParamList WithError { Accessor $1 $2 $3 }
| Comment { $1 }
WithError :: { Maybe StringNode }
WithError
: ';' { Nothing }
| with 'error' EnumeratorList { Just (ErrorList $3) }
| with 'error' for IdVar ';' { Just (ErrorFor $4) }
FunctionPrototype(id)
: QualType id FunctionParamList { FunctionPrototype $1 $2 $3 }
| QualType id FunctionParamList const { FunctionPrototype $1 $2 $3 }
FunctionParamList :: { [StringNode] }
FunctionParamList
: '(' ')' { [] }
| '(' void ')' { [TyStd $2] }
| '(' FunctionParams ')' { reverse $2 }
| '(' FunctionParams ',' '...' ')' { reverse $ Ellipsis : $2 }
FunctionParams :: { [StringNode] }
FunctionParams
: FunctionParam { [$1] }
| FunctionParams ',' FunctionParam { $3 : $1 }
FunctionParam :: { StringNode }
FunctionParam
: QualType DeclSpec { FunctionParam $1 $2 }
ConstDecl :: { StringNode }
ConstDecl
: extern const LeafType ID_VAR ';' { ConstDecl $3 $4 }
| const LeafType ID_VAR '=' InitialiserExpr ';' { ConstDefn Global $2 $3 $5 }
| static const LeafType ID_VAR '=' InitialiserExpr ';' { ConstDefn Static $3 $4 $6 }
{
type StringLexeme = Lexeme String
type StringNode = Node () StringLexeme
parseError :: Show text => (Lexeme text, [String]) -> Alex a
parseError (L (AlexPn _ line col) c t, options) =
alexError $ show line <> ":" <> show col <> ": Parse error near " <> show c <> ": "
<> show t <> "; expected one of " <> show options
lexwrap :: (Lexeme String -> Alex a) -> Alex a
lexwrap = (alexMonadScan >>=)
externC
:: Lexeme String
-> Lexeme String
-> [StringNode]
-> Lexeme String
-> Alex StringNode
externC (L _ _ "__cplusplus") (L _ _ "\"C\"") decls (L _ _ "__cplusplus") =
return $ ExternC decls
externC _ lang _ _ =
alexError $ show lang
<> ": extern \"C\" declaration invalid (did you spell __cplusplus right?)"
macroBodyStmt
:: [StringNode]
-> Lexeme String
-> Alex StringNode
macroBodyStmt decls (L _ _ "0") =
return $ MacroBodyStmt decls
macroBodyStmt _ cond =
alexError $ show cond
<> ": macro do-while body must end in 'while (0)'"
}