📄 php.ll
字号:
/* php.ll Copyright (c) 2001 Dragos Acostachioaie This file is part of DOC++. DOC++ is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the license, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/%{#include <assert.h>#include <ctype.h>#include <iostream.h>#include <stdio.h>#include "doc.h"static const char *inputString;static int inputPosition;static int lastContext;static int bracketCount = 0;static Entry *current_root = 0;static Entry *global_root = 0;static Entry *current = 0;// this one trackes whether we're looking for first-level classes (true)// or members and nested classes (false).static bool findClasses = false;static int yyLineNr = 0;static char yyFileName[264];static char ssEndChar;static int ssSave;// these two variables count brackets in two new flex-start-conditions.static int skip_to_semi_count = 0;static int skip_to_bracket_count = 0;static void msg(const char *str, const char *str2 = 0){#ifdef DEBUG if(verb) { printf("%s(%d): %s", yyFileName, yyLineNr, str); if(str2) printf("`%s'", str2); printf("\n"); }#endif}static void lineCount(){ for(const char *c = yytext; *c; ++c) yyLineNr += (*c == '\n');}#undef YY_INPUT#define YY_INPUT(buf, result, max_size) result = yyread(buf, max_size);static int yyread(char *buf, int max_size){ int c = 0; while(c < max_size && inputString[inputPosition]) { *buf = inputString[inputPosition++]; c++; buf++; } return c;}%}%x FindClasses%x ClassName%x ClassBody%x Require%x Include%x Extends%x Implements%x FindMembers%x Member%x SkipToBracket%x SkipToSemi%x Args%x Function%x Throws%x Comment%x SkipComment%x SkipString%x PHPDoc%x See%x Author%x Version%x Param%x Return%x Exception%x Precondition
%x Postcondition
%x Invariant
%x File%%<*>\x06[^\x06]*\x06 { int i; yyLineNr = 1; if(bracketCount != 0 || YY_START != FindClasses ) fprintf(stderr, "Warning end of duff file: `%s', {} %d, %d\n", yyFileName, bracketCount, YY_START); for(i = 0; yytext[i + 1] != 6; i++) yyFileName[i] = yytext[i + 1]; yyFileName[i] = 0; current_root = global_root; }<FindClasses>[ \t]*"class"[ \t]+ { current->section = CLASS_SEC; current->protection = PUBL; current->type += "class"; findClasses = true; BEGIN(ClassName); }<FindClasses>[ \t]*"function"[ \t]+ { if (current->section != CLASS_SEC) { current->section = FUNCTION_SEC; current->protection = PUBL; findClasses = true; BEGIN(Member); } }<Require>[a-z_A-Z0-9.*]* { current->import.append(new McString(yytext)); }<Require>; { BEGIN(FindClasses); }<Include>[a-z_A-Z0-9.*]* { current->import.append(new McString(yytext)); }<Include>; { BEGIN(FindClasses); }<ClassName>[ \t]*"extends"[ \t]* { BEGIN(Extends); }<ClassName>[ \t]*"{"[ \t]* { BEGIN(ClassBody); current->file = yyFileName; current->startLine = yyLineNr; }<ClassName>[a-z_A-Z0-9]+ { current->name = yytext; msg("found class ", yytext); }<Extends>[a-z_A-Z.0-9]+ { current->extends.append(new McString(yytext)); msg(" Extends : ",yytext); BEGIN(ClassName); }<ClassBody>[ \t\n]*"/*""*"*[ \t]* { current->program += yytext; lineCount(); lastContext = YY_START; BEGIN(Comment); }<ClassBody>"{" { current->program += yytext; ++bracketCount; }<ClassBody>"}" { if(bracketCount) { current->program += yytext; --bracketCount; } else { current_root->addSubEntry(current); current = new Entry; if(findClasses) BEGIN(FindClasses); else BEGIN(FindMembers); } }<ClassBody>\n { current->program += yytext; yyLineNr++; }<ClassBody>\/\/.*\n { current->program += yytext; }<ClassBody>[\"\'] { ssEndChar = *yytext; ssSave = 0; lastContext = YY_START; BEGIN(SkipString); }<ClassBody>. { current->program += yytext; }<FindMembers>";" { current->name.clear(); current->type.clear(); current->args.clear(); current->program.clear(); current->doc.clear(); current->section = EMPTY_SEC; }<FindMembers>[ \t]*"var"[ \t]* { current->protection = PUBL; current->type += ""; }<FindMembers>[a-z_A-Z.0-9]+ { // if we find a non-keyword word, make note of it and go to rule <Member> if(current->type.length()) current->type += ' '; current->protection = PUBL; current->type += current->name; current->name = yytext; BEGIN(Member); }<Member>[a-z_A-Z.0-9]+ {// The rule <Member> I had to make a small adjustment:// splitting <Member>[;=] into <Member>";" and <Member>"="// (see below for explaination) if(current->type.length()) current->type += ' '; current->type += current->name; current->name = yytext; }<Member>"," {// this is "business as usual" current->section = VARIABLE_SEC; current_root->addSubEntry(current); msg("found field ", current->name.c_str()); current = new Entry; BEGIN(Member); }<Member>";" {// this is "business as usual" current->section = VARIABLE_SEC; current_root->addSubEntry(current); msg("found field ", current->name.c_str()); current = new Entry; BEGIN(FindMembers); }<Member>"=" {// we made this an extra rule because otherwise the initialized had been// treated as Member (which it obviously isn't). So if we have an "=", we go to// a new rule <SkipToSemi> where we skip everything including the ending ";"// then we go to FindMembers current->section = VARIABLE_SEC; current_root->addSubEntry(current); msg("found field ", current->name.c_str()); current = new Entry; skip_to_semi_count = 0; // we count bracket-levels "{}" BEGIN(SkipToSemi); }<SkipToSemi>"{" {// We take care for bracket-levels because there might be definition of an// anonymous class here that makes use of Semicolons we are not interested in. skip_to_semi_count++; }<SkipToSemi>"(" { skip_to_semi_count++; }<SkipToSemi>"[" { skip_to_semi_count++; }<SkipToSemi>"}" { skip_to_semi_count--; }<SkipToSemi>")" { skip_to_semi_count--; }<SkipToSemi>"]" { skip_to_semi_count--; }<SkipToSemi>";" {// So if there is a semicolon at "our" bracket level, we expect members again. if(skip_to_semi_count == 0) BEGIN(FindMembers); }<Member>"(" { current->section = FUNCTION_SEC; current->protection = PUBL; current->args = yytext; msg("found method ", current->name.c_str()); BEGIN(Args); }<Args>")" { current->args += *yytext; BEGIN(Function); }<Args>. { current->args += *yytext; }<Function>";" { current_root->addSubEntry(current); current = new Entry; BEGIN(FindMembers); }<Function>"{" { current_root->addSubEntry(current); current = new Entry; skip_to_bracket_count = 1; // we take care of bracket level BEGIN(SkipToBracket); }<SkipToBracket>"{" { // this skips the function body. skip_to_bracket_count++; }<SkipToBracket>"}" { if(--skip_to_bracket_count == 0) if (findClasses) BEGIN(FindClasses); else BEGIN(FindMembers); }<Comment>\n { current->program += yytext; yyLineNr++; }<Comment>. { current->program += yytext; }<Comment>.*"*/" { current->program += yytext; BEGIN(lastContext); }<SkipComment>[ \t]*"*/" { BEGIN(lastContext); }<SkipComment>"/*""*"*"*/"<SkipComment>[ \t\n]*"/**""*"*[ \t]*<SkipString>[\"\'] { if(*yytext == ssEndChar) BEGIN(lastContext); if(ssSave) current->program += *yytext; }<SkipString>\\. { if(ssSave) current->program += yytext; }<SkipString>. { if(ssSave) current->program += *yytext; }<FindClasses,ClassName,Require,Include,Extends,Implements,FindMembers,Member,Args,Function,See,Author,Version,Param,Return,Exception,Precondition,Postcondition,Invariant>[ \t\n]*"/**""*"*[ \t]* { lastContext = YY_START; lineCount(); current->doc.clear(); BEGIN(PHPDoc); }<PHPDoc>\n { current->doc += *yytext; yyLineNr++; }<PHPDoc>[\n \t]*"*"+"/" {// Before the fix, it was context-sensitive which state to go next - depending// on current->section. I changed this, since it doesn't make sense. BEGIN(lastContext); }<PHPDoc>\n[ \t]*"*"*[ \t]* { current->doc += '\n'; yyLineNr++; }<PHPDoc>. { current->doc += *yytext; }<FindClasses,ClassName,Require,Include,Extends,Implements,FindMembers,Member,Args,Function,See,Author,Version,Param,Return,Exception,Precondition,Postcondition,Invariant>"/*" { if(YY_START != SkipComment) // Default rules are hellspawn lastContext = YY_START; BEGIN(SkipComment); }<FindClasses,ClassName,Require,Include,Extends,Implements,FindMembers,Member,Args,Function,See,Author,Version,Param,Return,Exception,Precondition,Postcondition,Invariant>[ \t]*"*/" { BEGIN(lastContext); }<FindClasses,ClassName,Require,Include,Extends,Implements,FindMembers,Member,Args,Function,See,Author,Version,Param,Return,Exception,Precondition,Postcondition,Invariant>"/*""*"*"*/"<FindClasses,ClassName,Require,Include,Extends,Implements,FindMembers,Member,Args,Function,See,Author,Version,Param,Return,Exception,Precondition,Postcondition,Invariant>[\"\'] { ssEndChar = *yytext; ssSave = 0; lastContext = YY_START; BEGIN(SkipString); }<FindClasses,ClassName,Require,Include,Extends,Implements,FindMembers,Member,Args,Function,See,Author,Version,Param,Return,Exception,Precondition,Postcondition,Invariant>\/\/.*\n<*>.<*>\n { yyLineNr++; }%%void parsePHPClasses(Entry *rt){ if(rt == 0) return; for(Entry *cr = rt->sub; cr; cr = cr->next) { if(cr->program.length()) { inputString = cr->program.c_str(); inputPosition = 0; phpYYrestart(phpYYin); // We're looking for members and nested classes. findClasses = false; BEGIN(FindMembers); current_root = cr; strcpy(yyFileName, cr->file.c_str()); yyLineNr = cr->startLine; phpYYlex(); cr->program.clear(); } parsePHPClasses(cr); } parseDoc(rt);}void parsePHP(Entry *rt){ assert(rt); current_root = rt; global_root = rt; current = new Entry; inputString = rt->program.c_str(); inputPosition = 0; phpYYrestart(phpYYin); // We're looking for first-level Classes. BEGIN(FindClasses); findClasses = true; phpYYlex(); rt->program.clear(); parsePHPClasses(rt); delete current;}extern "C" { int phpYYwrap() { return 1; }};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -