📄 parser.y
字号:
/* * The SIP parser. * * Copyright (c) 2006 * Riverbank Computing Limited <info@riverbankcomputing.co.uk> * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */%{#include <stdlib.h>#include <string.h>#include <ctype.h>#include "sip.h"#define MAX_NESTED_IF 10#define MAX_NESTED_SCOPE 10#define inMainModule() (currentSpec -> module == currentModule)static sipSpec *currentSpec; /* The current spec being parsed. */static stringList *neededQualifiers; /* The list of required qualifiers. */static stringList *excludedQualifiers; /* The list of excluded qualifiers. */static moduleDef *currentModule; /* The current module being parsed. */static mappedTypeDef *currentMappedType; /* The current mapped type. */static enumDef *currentEnum; /* The current enum being parsed. */static int sectionFlags; /* The current section flags. */static int currentOverIsVirt; /* Set if the overload is virtual. */static int currentCtorIsExplicit; /* Set if the ctor is explicit. */static int currentIsStatic; /* Set if the current is static. */static char *previousFile; /* The file just parsed. */static parserContext newContext; /* The new pending context. */static int skipStackPtr; /* The skip stack pointer. */static int skipStack[MAX_NESTED_IF]; /* Stack of skip flags. */static classDef *scopeStack[MAX_NESTED_SCOPE]; /* The scope stack. */static int sectFlagsStack[MAX_NESTED_SCOPE]; /* The section flags stack. */static int currentScopeIdx; /* The scope stack index. */static int currentTimelineOrder; /* The current timeline order. */static char *getPythonName(optFlags *optflgs, char *cname);static nameDef *cacheName(sipSpec *,char *);static classDef *findClass(sipSpec *,ifaceFileType,scopedNameDef *);static classDef *findClassWithInterface(sipSpec *pt, ifaceFileDef *iff);static classDef *newClass(sipSpec *,ifaceFileType,scopedNameDef *);static void finishClass(sipSpec *,moduleDef *,classDef *,optFlags *);static exceptionDef *findException(sipSpec *pt, scopedNameDef *fqname, int new);static mappedTypeDef *newMappedType(sipSpec *,argDef *);static enumDef *newEnum(sipSpec *,moduleDef *,char *,optFlags *,int);static void instantiateClassTemplate(sipSpec *pt, moduleDef *mod, classDef *scope, scopedNameDef *fqname, classTmplDef *tcd, templateDef *td);static void newTypedef(sipSpec *,moduleDef *,char *,argDef *);static void newVar(sipSpec *,moduleDef *,char *,int,argDef *,optFlags *, codeBlock *,codeBlock *,codeBlock *);static void newCtor(char *,int,signatureDef *,optFlags *,codeBlock *, throwArgs *,signatureDef *,int);static void newFunction(sipSpec *,moduleDef *,int,int,int,char *, signatureDef *,int,int,optFlags *,codeBlock *, codeBlock *,throwArgs *,signatureDef *);static optFlag *findOptFlag(optFlags *,char *,flagType);static memberDef *findFunction(sipSpec *,moduleDef *,classDef *,nameDef *,int, int);static void checkAttributes(sipSpec *,classDef *,char *,int);static void newModule(FILE *,char *);static void appendCodeBlock(codeBlock **,codeBlock *);static void parseFile(FILE *,char *,moduleDef *,int);static void handleEOF(void);static void handleEOM(void);static qualDef *findQualifier(char *);static scopedNameDef *text2scopedName(char *);static scopedNameDef *scopeScopedName(scopedNameDef *name);static void pushScope(classDef *);static void popScope(void);static classDef *currentScope(void);static void newQualifier(moduleDef *,int,int,char *,qualType);static void newImport(char *);static void usedInMainModule(sipSpec *,ifaceFileDef *);static int timePeriod(char *,char *);static int platOrFeature(char *,int);static int isNeeded(qualDef *);static int notSkipping(void);static void getHooks(optFlags *,char **,char **);static int getReleaseGIL(optFlags *);static void templateSignature(signatureDef *sd, int result, classTmplDef *tcd, templateDef *td, classDef *ncd);static void templateType(argDef *ad, classTmplDef *tcd, templateDef *td, classDef *ncd);static int search_back(const char *end, const char *start, const char *target);static char *getType(scopedNameDef *ename, argDef *ad);static char *scopedNameToString(scopedNameDef *name);static void addUsedFromCode(sipSpec *pt, ifaceFileList **used, const char *sname);static int sameName(scopedNameDef *snd, const char *sname);%}%union { char qchar; char *text; long number; double real; argDef memArg; signatureDef signature; signatureDef *optsignature; throwArgs *throwlist; codeBlock *codeb; valueDef value; valueDef *valp; optFlags optflags; optFlag flag; scopedNameDef *scpvalp; fcallDef fcall; int boolean; exceptionDef exceptionbase; classDef *klass;}%token TK_NOEMITTERS%token TK_DOC%token TK_EXPORTEDDOC%token TK_MAKEFILE%token TK_ACCESSCODE%token TK_GETCODE%token TK_SETCODE%token TK_PREINITCODE%token TK_POSTINITCODE%token TK_MODCODE%token TK_TYPECODE%token TK_PREPYCODE%token TK_COPYING%token TK_MAPPEDTYPE%token <codeb> TK_CODELINE%token TK_IF%token TK_END%token <text> TK_NAME%token <text> TK_PATHNAME%token <text> TK_STRING%token TK_VIRTUALCATCHERCODE%token TK_TRAVERSECODE%token TK_CLEARCODE%token TK_READBUFFERCODE%token TK_WRITEBUFFERCODE%token TK_SEGCOUNTCODE%token TK_CHARBUFFERCODE%token TK_METHODCODE%token TK_FROMTYPE%token TK_TOTYPE%token TK_TOSUBCLASS%token TK_INCLUDE%token TK_OPTINCLUDE%token TK_IMPORT%token TK_MODHEADERCODE%token TK_TYPEHEADERCODE%token TK_MODULE%token TK_CMODULE%token TK_CLASS%token TK_STRUCT%token TK_PUBLIC%token TK_PROTECTED%token TK_PRIVATE%token TK_SIGNALS%token TK_SLOTS%token TK_BOOL%token TK_SHORT%token TK_INT%token TK_LONG%token TK_FLOAT%token TK_DOUBLE%token TK_CHAR%token TK_VOID%token TK_PYOBJECT%token TK_PYTUPLE%token TK_PYLIST%token TK_PYDICT%token TK_PYCALLABLE%token TK_PYSLICE%token TK_PYTYPE%token TK_VIRTUAL%token TK_ENUM%token TK_SIGNED%token TK_UNSIGNED%token TK_SCOPE%token TK_LOGICAL_OR%token TK_CONST%token TK_STATIC%token TK_SIPSIGNAL%token TK_SIPSLOT%token TK_SIPANYSLOT%token TK_SIPRXCON%token TK_SIPRXDIS%token TK_SIPSLOTCON%token TK_SIPSLOTDIS%token <number> TK_NUMBER%token <real> TK_REAL%token TK_TYPEDEF%token TK_NAMESPACE%token TK_TIMELINE%token TK_PLATFORMS%token TK_FEATURE%token TK_LICENSE%token <qchar> TK_QCHAR%token TK_TRUE%token TK_FALSE%token TK_NULL%token TK_OPERATOR%token TK_THROW%token TK_QOBJECT%token TK_EXCEPTION%token TK_RAISECODE%token TK_EXPLICIT%token TK_TEMPLATE%token TK_ELLIPSIS%type <memArg> argvalue%type <memArg> argtype%type <memArg> cpptype%type <memArg> basetype%type <signature> template%type <signature> arglist%type <signature> rawarglist%type <signature> cpptypelist%type <optsignature> optsig%type <optsignature> optctorsig%type <throwlist> optexceptions%type <throwlist> exceptionlist%type <number> optslot%type <number> optref%type <number> optconst%type <number> optvirtual%type <number> optabstract%type <number> deref%type <number> optnumber%type <value> simplevalue%type <valp> value%type <valp> expr%type <valp> optassign%type <codeb> optaccesscode%type <codeb> optgetcode%type <codeb> optsetcode%type <codeb> modhdrcode%type <codeb> typehdrcode%type <codeb> opttypehdrcode%type <codeb> travcode%type <codeb> clearcode%type <codeb> readbufcode%type <codeb> writebufcode%type <codeb> segcountcode%type <codeb> charbufcode%type <codeb> modcode%type <codeb> typecode%type <codeb> codeblock%type <codeb> codelines%type <codeb> virtualcatchercode%type <codeb> methodcode%type <codeb> raisecode%type <text> operatorname%type <text> optfilename%type <text> optname%type <text> modname%type <optflags> optflags%type <optflags> flaglist%type <flag> flag%type <flag> flagvalue%type <qchar> optunop%type <qchar> binop%type <scpvalp> scopepart%type <scpvalp> scopedname%type <fcall> exprlist%type <boolean> qualifiers%type <boolean> oredqualifiers%type <boolean> modlang%type <boolean> optclassbody%type <exceptionbase> baseexception%type <klass> class%%specification: statement | specification statement ;statement: { /* * We don't do these in parserEOF() because the parser * is reading ahead and that would be too early. */ if (previousFile != NULL) { handleEOF(); if (newContext.prevmod != NULL) handleEOM(); free(previousFile); previousFile = NULL; } } modstatement ;modstatement: module | noemitters | copying | include | optinclude | import | timeline | platforms | feature | license | modhdrcode { if (notSkipping() && inMainModule()) appendCodeBlock(¤tSpec -> hdrcode,$1); } | modcode { if (notSkipping() && inMainModule()) appendCodeBlock(¤tSpec -> cppcode,$1); } | preinitcode | postinitcode | prepycode | doc | exporteddoc | makefile | mappedtype | mappedtypetmpl | nsstatement ;nsstatement: ifstart | ifend | namespace | struct | class | classtmpl | exception | typedef | enum | function | variable | typehdrcode { if (notSkipping()) { classDef *scope = currentScope(); if (scope == NULL) yyerror("%TypeHeaderCode can only be used in a namespace, class or mapped type"); appendCodeBlock(&scope->hdrcode, $1); } } ;noemitters: TK_NOEMITTERS { if (notSkipping()) currentSpec->emitters = FALSE; } ;exception: TK_EXCEPTION scopedname baseexception optflags '{' opttypehdrcode raisecode '}' ';' { if (notSkipping()) { exceptionDef *xd; char *pyname; if (currentSpec->genc) yyerror("%Exception not allowed in a C module"); pyname = getPythonName(&$4, scopedNameTail($2)); checkAttributes(currentSpec, NULL, pyname, FALSE); xd = findException(currentSpec, $2, TRUE); if (xd->cd != NULL) yyerror("%Exception name has already been seen as a class name - it must be defined before being used"); if (xd->iff->module != NULL) yyerror("The %Exception has already been defined"); /* Complete the definition. */ xd->iff->module = currentModule; xd->pyname = pyname; xd->bibase = $3.bibase; xd->base = $3.base; xd->hdrcode = $6; xd->raisecode = $7; if (xd->bibase != NULL || xd->base != NULL) xd->exceptionnr = currentModule->nrexceptions++; if (inMainModule() && xd->base != NULL && xd->base->iff->module != currentModule) addToUsedList(¤tSpec->used, xd->base->iff); } } ;baseexception: { $$.bibase = NULL; $$.base = NULL; } | '(' scopedname ')' { exceptionDef *xd; $$.bibase = NULL; $$.base = NULL; /* See if it is a defined exception. */ for (xd = currentSpec->exceptions; xd != NULL; xd = xd->next) if (sameScopedName(xd->iff->fqcname, $2)) { $$.base = xd; break; } if (xd == NULL && $2->next == NULL && strncmp($2->name, "SIP_", 4) == 0) { /* See if it is a builtin exception. */ static char *builtins[] = { "Exception", "StopIteration", "StandardError", "ArithmeticError", "LookupError", "AssertionError", "AttributeError", "EOFError", "FloatingPointError", "EnvironmentError", "IOError", "OSError", "ImportError", "IndexError", "KeyError", "KeyboardInterrupt", "MemoryError", "NameError", "OverflowError", "RuntimeError", "NotImplementedError", "SyntaxError", "IndentationError", "TabError", "ReferenceError", "SystemError", "SystemExit", "TypeError", "UnboundLocalError", "UnicodeError", "UnicodeEncodeError", "UnicodeDecodeError", "UnicodeTranslateError", "ValueError", "ZeroDivisionError", "WindowsError", "VMSError", NULL }; char **cp; for (cp = builtins; *cp != NULL; ++cp) if (strcmp($2->name + 4, *cp) == 0) { $$.bibase = *cp; break; } } if ($$.bibase == NULL && $$.base == NULL) yyerror("Unknown exception base type"); } ;raisecode: TK_RAISECODE codeblock { $$ = $2; } ;mappedtype: TK_MAPPEDTYPE basetype { if (notSkipping()) currentMappedType = newMappedType(currentSpec,&$2); } mtdefinition ;mappedtypetmpl: template TK_MAPPEDTYPE basetype { int a; if (currentSpec->genc) yyerror("%MappedType templates not allowed in a C module"); /* * Check the template arguments are all just simple * names. */ for (a = 0; a < $1.nrArgs; ++a) if ($1.args[a].atype != defined_type || $1.args[a].u.snd->next != NULL) yyerror("%MappedType template arguments must be simple names"); if ($3.atype != template_type) yyerror("%MappedType template must map a template type"); if (notSkipping()) { mappedTypeTmplDef *mtt; /* * Check a template hasn't already been * provided. */ for (mtt = currentSpec->mappedtypetemplates; mtt != NULL; mtt = mtt->next) if (sameScopedName(mtt->mt->type.u.td->fqname, $3.u.td->fqname) && sameTemplateSignature(&mtt->mt->type.u.td->types, &$3.u.td->types, TRUE)) yyerror("%MappedType template for this type has already been defined"); $3.nrderefs = 0; $3.argflags = 0; mtt = sipMalloc(sizeof (mappedTypeTmplDef)); mtt->sig = $1; mtt->mt = allocMappedType(&$3); mtt->next = currentSpec->mappedtypetemplates; currentSpec->mappedtypetemplates = mtt; currentMappedType = mtt->mt; } } mtdefinition ;mtdefinition: '{' mtbody '}' ';' { if (notSkipping()) { if (currentMappedType->convfromcode == NULL) yyerror("%MappedType must have a %ConvertFromTypeCode directive"); if (currentMappedType->convtocode == NULL) yyerror("%MappedType must have a %ConvertToTypeCode directive"); currentMappedType = NULL; } } ;mtbody: mtline | mtbody mtline ;mtline: typehdrcode { if (notSkipping()) appendCodeBlock(¤tMappedType -> hdrcode,$1); } | TK_FROMTYPE codeblock { if (notSkipping()) { if (currentMappedType -> convfromcode != NULL) yyerror("%MappedType has more than one %ConvertFromTypeCode directive"); currentMappedType -> convfromcode = $2; } } | TK_TOTYPE codeblock { if (notSkipping()) { if (currentMappedType -> convtocode != NULL) yyerror("%MappedType has more than one %ConvertToTypeCode directive"); currentMappedType -> convtocode = $2; } } ;namespace: TK_NAMESPACE TK_NAME { if (currentSpec -> genc) yyerror("namespace definition not allowed in a C module"); if (notSkipping()) { classDef *ns; ns = newClass(currentSpec,namespace_iface,text2scopedName($2)); pushScope(ns); sectionFlags = 0; } } '{' nsbody '}' ';' { if (inMainModule()) { classDef *ns = currentScope(); if (!isUsedName(ns->iff->name)) { varDef *vd; for (vd = currentSpec->vars; vd != NULL; vd = vd->next) if (vd->ecd == ns) { setIsUsedName(ns->iff->name); break; } } } if (notSkipping()) popScope(); } ;nsbody: nsstatement | nsbody nsstatement ;platforms: TK_PLATFORMS { qualDef *qd; for (qd = currentModule -> qualifiers; qd != NULL; qd = qd -> next) if (qd -> qtype == platform_qualifier)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -