📄 lexer.l
字号:
/* * The SIP lexer. * * 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 <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include "sip.h"#include "parser.h"#ifndef FLEX_SCANNER#error "Only flex is supported at the moment"#endif#define YY_FATAL_ERROR(s) fatallex(s)#define MAX_INCLUDE_DEPTH 10#define MAX_CODE_LINE_LENGTH 1000static struct inputFile { int lineno; /* The line number. */ YY_BUFFER_STATE bs; /* The flex buffer state handle. */ char *name; /* The file name. */ char *cwd; /* The path part of the file name. */ parserContext pc; /* The parser context. */} inputFileStack[MAX_INCLUDE_DEPTH];static int currentFile = -1; /* Index of the current input file. */static char codeLine[MAX_CODE_LINE_LENGTH + 2]; /* The current code line. */static int codeIdx = -1; /* Index of next code character. */static FILE *openFile(char *);static void fatallex(char *);%}%x code%x ccomment%%^[ \t]*%SIPNoEmitters {return TK_NOEMITTERS;}^[ \t]*%Include {return TK_INCLUDE;}^[ \t]*%OptionalInclude {return TK_OPTINCLUDE;}^[ \t]*%Import {return TK_IMPORT;}^[ \t]*%Module {return TK_MODULE;}^[ \t]*%CModule {return TK_CMODULE;}^[ \t]*%Timeline {return TK_TIMELINE;}^[ \t]*%Platforms {return TK_PLATFORMS;}^[ \t]*%Feature {return TK_FEATURE;}^[ \t]*%License {return TK_LICENSE;}^[ \t]*%MappedType {return TK_MAPPEDTYPE;}^[ \t]*%Exception {return TK_EXCEPTION;}^[ \t]*%If {return TK_IF;}<INITIAL>^[ \t]*%End {return TK_END;}class {return TK_CLASS;}struct {return TK_STRUCT;}public {return TK_PUBLIC;}protected {return TK_PROTECTED;}private {return TK_PRIVATE;}signals {return TK_SIGNALS;}slots {return TK_SLOTS;}char {return TK_CHAR;}bool {return TK_BOOL;}short {return TK_SHORT;}int {return TK_INT;}long {return TK_LONG;}float {return TK_FLOAT;}double {return TK_DOUBLE;}void {return TK_VOID;}virtual {return TK_VIRTUAL;}enum {return TK_ENUM;}signed {return TK_SIGNED;}unsigned {return TK_UNSIGNED;}const {return TK_CONST;}static {return TK_STATIC;}true {return TK_TRUE;}false {return TK_FALSE;}NULL {return TK_NULL;}typedef {return TK_TYPEDEF;}namespace {return TK_NAMESPACE;}operator {return TK_OPERATOR;}throw {return TK_THROW;}explicit {return TK_EXPLICIT;}template {return TK_TEMPLATE;}:: {return TK_SCOPE;}\|\| {return TK_LOGICAL_OR;}SIP_PYOBJECT {return TK_PYOBJECT;}SIP_PYTUPLE {return TK_PYTUPLE;}SIP_PYLIST {return TK_PYLIST;}SIP_PYDICT {return TK_PYDICT;}SIP_PYCALLABLE {return TK_PYCALLABLE;}SIP_PYSLICE {return TK_PYSLICE;}SIP_PYTYPE {return TK_PYTYPE;}SIP_SIGNAL {return TK_SIPSIGNAL;}SIP_SLOT {return TK_SIPSLOT;}SIP_ANYSLOT {return TK_SIPANYSLOT;}SIP_RXOBJ_CON {return TK_SIPRXCON;}SIP_RXOBJ_DIS {return TK_SIPRXDIS;}SIP_SLOT_CON {return TK_SIPSLOTCON;}SIP_SLOT_DIS {return TK_SIPSLOTDIS;}SIP_QOBJECT {return TK_QOBJECT;}\.\.\. {return TK_ELLIPSIS;}[ \t] { /* Ignore whitespace. */ ;}\n { /* Maintain the line number. */ ++inputFileStack[currentFile].lineno; if (codeIdx == 0) { BEGIN code; }}\/\/.* { /* Ignore C++ style comments. */ ;}-?[0-9]+ { /* A signed decimal number. */ yylval.number = strtol(yytext,NULL,0); return TK_NUMBER;}-?(([0-9]+)|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) {/* A floating point number. */ yylval.real = strtod(yytext,NULL); return TK_REAL;}0x[0-9a-fA-F]+ { /* An unsigned hexadecimal number. */ yylval.number = strtol(yytext,NULL,16); return TK_NUMBER;}[_A-Za-z][_A-Za-z0-9]* { /* An identifier name. */ yylval.text = sipStrdup(yytext); return TK_NAME;}[._A-Za-z][._/A-Za-z0-9\-]*[._A-Za-z0-9] { /* A relative pathname. */ yylval.text = sipStrdup(yytext); return TK_PATHNAME;}\"[^"\n]*["\n] { /* A double-quoted string. */ char *dp, *sp; /* Copy the string without the quotes. */ yylval.text = sipMalloc(strlen(yytext) + 1); dp = yylval.text; sp = yytext; while (*sp != '\0') { if (*sp != '"') *dp++ = *sp; ++sp; } *dp = '\0'; return TK_STRING;}\'[^'\n]*['\n] { /* A single-quoted character. */ if (strlen(yytext) != 3) fatallex("Exactly one character expected between single quotes"); yylval.qchar = yytext[1]; return TK_QCHAR;}\/\* { /* Ignore C-style comments. */ BEGIN ccomment;}<ccomment>\n { ++inputFileStack[currentFile].lineno;}<ccomment>\*\/ { BEGIN INITIAL;}<ccomment>. { ;}^%Copying { /* The software license. */ codeIdx = 0; return TK_COPYING;}^%ConvertFromTypeCode { /* The start of a from-type code block. */ codeIdx = 0; return TK_FROMTYPE;}^%ConvertToTypeCode { /* The start of a to-type code block. */ codeIdx = 0; return TK_TOTYPE;}^%ConvertToSubClassCode { /* The start of a to-sub-class code block. */ codeIdx = 0; return TK_TOSUBCLASS;}^%ModuleHeaderCode { /* The start of a module header code block. */ codeIdx = 0; return TK_MODHEADERCODE;}^%TypeHeaderCode { /* The start of a type header code block. */ codeIdx = 0; return TK_TYPEHEADERCODE;}^%PreInitialisationCode { /* The start of a pre-initialisation code block. */ codeIdx = 0; return TK_PREINITCODE;}^%PostInitialisationCode { /* The start of a post-initialisation code block. */ codeIdx = 0; return TK_POSTINITCODE;}^%ModuleCode { /* The start of a module code block. */ codeIdx = 0; return TK_MODCODE;}^%TypeCode { /* The start of a type code block. */ codeIdx = 0; return TK_TYPECODE;}^%MethodCode { /* The start of a C++ method code block. */ codeIdx = 0; return TK_METHODCODE;}^%VirtualCatcherCode { /* The start of a C++ virtual code block. */ codeIdx = 0; return TK_VIRTUALCATCHERCODE;}^%GCTraverseCode { /* The start of a traverse code block. */ codeIdx = 0; return TK_TRAVERSECODE;}^%GCClearCode { /* The start of a clear code block. */ codeIdx = 0; return TK_CLEARCODE;}^%BIGetReadBufferCode { /* The start of a read buffer code block. */ codeIdx = 0; return TK_READBUFFERCODE;}^%BIGetWriteBufferCode { /* The start of a write buffer code block. */ codeIdx = 0; return TK_WRITEBUFFERCODE;}^%BIGetSegCountCode { /* The start of a segment count code block. */ codeIdx = 0; return TK_SEGCOUNTCODE;}^%BIGetCharBufferCode { /* The start of a char buffer code block. */ codeIdx = 0; return TK_CHARBUFFERCODE;}^%PrePythonCode { /* The start of a pre-Python code block. */ codeIdx = 0; return TK_PREPYCODE;}^%RaiseCode { /* The start of a raise exception code block. */ codeIdx = 0; return TK_RAISECODE;}^%Doc { /* The start of a documentation block. */ codeIdx = 0; return TK_DOC;}^%ExportedDoc { /* The start of an exported documentation block. */ codeIdx = 0; return TK_EXPORTEDDOC;}^%Makefile { /* The start of a Makefile code block. */ codeIdx = 0; return TK_MAKEFILE;}^%AccessCode { /* The start of an access code block. */ codeIdx = 0; return TK_ACCESSCODE;}^%GetCode { /* The start of a get code block. */ codeIdx = 0; return TK_GETCODE;}^%SetCode { /* The start of a set code block. */ codeIdx = 0; return TK_SETCODE;}<code>^%End { /* The end of a code block. */ BEGIN INITIAL; codeIdx = -1; return TK_END;}<code>\n { /* The end of a code line . */ struct inputFile *ifp; codeLine[codeIdx] = '\n'; codeLine[codeIdx + 1] = '\0'; codeIdx = 0; ifp = &inputFileStack[currentFile]; yylval.codeb = sipMalloc(sizeof (codeBlock)); yylval.codeb -> frag = sipStrdup(codeLine); yylval.codeb -> linenr = ifp -> lineno++; yylval.codeb -> filename = sipStrdup(ifp -> name); yylval.codeb -> next = NULL; return TK_CODELINE;}<code>. { /* The contents of a code line. */ if (codeIdx == MAX_CODE_LINE_LENGTH) fatallex("Line is too long"); codeLine[codeIdx++] = yytext[0];}. { /* Anything else is returned as is. */ return yytext[0];}%%/* * Hook into EOF handling. Return 0 if there is more to process. */int yywrap(){ char *cwd; struct inputFile *ifp; if ((cwd = inputFileStack[currentFile].cwd) != NULL) free(cwd); ifp = &inputFileStack[currentFile--]; /* Tell the parser if this is the end of a file. */ parserEOF(ifp -> name,&ifp -> pc); /* Tidy up this file. */ fclose(yyin); free(ifp -> name); /* See if this was the original file. */ if (currentFile < 0) return 1; yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(ifp -> bs); return 0;}/* * Set up an input file to be read by the lexer, opening it if necessary. */void setInputFile(FILE *fp,char *name,parserContext *pc,int optional){ char *fullname = NULL; if (currentFile >= MAX_INCLUDE_DEPTH - 1) fatal("Too many nested %%Include, %%OptionalInclude or %%Import statements\n"); if (fp != NULL || (fp = openFile(name)) != NULL) fullname = sipStrdup(name); else { char *cwd; /* Try the directory that contains the current file. */ if (currentFile >= 0 && (cwd = inputFileStack[currentFile].cwd) != NULL) { fullname = concat(cwd,"/",name,NULL); if ((fp = openFile(fullname)) == NULL) { free(fullname); fullname = NULL; } } } /* Try the include path if we haven't found anything yet. */ if (fullname == NULL) { stringList *sl; fullname = NULL; for (sl = includeDirList; sl != NULL; sl = sl -> next) { if (fullname != NULL) free(fullname); fullname = concat(sl -> s,"/",name,NULL); if ((fp = openFile(fullname)) != NULL) break; } if (fp == NULL && !optional) fatal("Unable to find file \"%s\"\n",name); } if (fp != NULL) { char *cwd; yyin = fp; ++currentFile; /* * Remember the directory containing the new file and make it * "current". */ if ((cwd = strchr(fullname,'/')) != NULL) { cwd = sipStrdup(fullname); *strrchr(cwd,'/') = '\0'; } inputFileStack[currentFile].lineno = 1; inputFileStack[currentFile].name = fullname; inputFileStack[currentFile].pc = *pc; inputFileStack[currentFile].cwd = cwd; if (currentFile > 0) { inputFileStack[currentFile].bs = YY_CURRENT_BUFFER; yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE)); } }}/* * Open a file for reading or return NULL if it doesn't exist. Any other error * is fatal. */static FILE *openFile(char *name){ FILE *fp; if ((fp = fopen(name,"r")) == NULL && errno != ENOENT) fatal("Error in opening file %s\n",name); return fp;}/* * Handle fatal yacc errors. */void yyerror(char *s){ if (currentFile < 0) fatal("Unexpected end of input\n"); fatal("%s:%d: %s\n", inputFileStack[currentFile].name, inputFileStack[currentFile].lineno, s);}/* * Handle warnings while parsing. */void yywarning(char *s){ warning("%s:%d: %s\n", inputFileStack[currentFile].name, inputFileStack[currentFile].lineno, s);}/* * Handle fatal lex errors. */static void fatallex(char *s){ fatal("%s:%d: Lexical analyser error: %s\n", inputFileStack[currentFile].name, inputFileStack[currentFile].lineno, s);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -