Пример #1
0
 private bool ScanPreProcessorDirective(bool insideExcludedBlock, int nonExcludedEndifCount){
   bool exclude = insideExcludedBlock;
   int savedStartPos = this.startPos;
   int i = this.startPos-1;
   while (i > 0 && Scanner.IsBlankSpace(this.GetChar(i))){
     i--;
   }
   if (i > 0 && !this.IsLineTerminator(this.GetChar(i), 0)){
     this.HandleError(Error.BadDirectivePlacement);
     goto skipToEndOfLine;
   }
   this.SkipBlanks(); //Check EOL/EOF?
   this.startPos = this.endPos-1;
   this.ScanIdentifier();
   switch (this.GetIdentifierString()){
     case "define": 
       if (insideExcludedBlock) goto skipToEndOfLine;
       if (!this.allowPPDefinitions){
         this.HandleError(Error.PPDefFollowsToken);
         goto skipToEndOfLine;
       }
       this.startPos = this.endPos;
       char chr = this.SkipBlanks();
       if (this.IsEndLineOrEOF(chr, 0)){
         this.HandleError(Error.ExpectedIdentifier);
         break;
       }
       this.identifier.Length = 0;
       this.endPos--;
       this.startPos = this.endPos;
       if (!this.IsIdentifierStartChar(chr))
         this.HandleError(Error.ExpectedIdentifier);
       else{
         this.ScanIdentifier();
         if (this.PreprocessorDefinedSymbols == null){
           this.PreprocessorDefinedSymbols = new Hashtable();
           this.PreprocessorDefinedSymbols["true"] = "true";
         }
         string s = this.GetIdentifierString();
         if (s == "true" || s == "false" || !this.IsIdentifierStartChar(s[0])){
           this.HandleError(Error.ExpectedIdentifier);
           goto skipToEndOfLine;
         }else
           this.PreprocessorDefinedSymbols[s] = s;
       }
       break;
     case "undef":
       if (insideExcludedBlock) goto skipToEndOfLine;
       if (!this.allowPPDefinitions){
         this.HandleError(Error.PPDefFollowsToken);
         goto skipToEndOfLine;
       }
       this.startPos = this.endPos;
       chr = this.SkipBlanks();
       if (this.IsEndLineOrEOF(chr, 0)){
         this.HandleError(Error.ExpectedIdentifier);
         break;
       }
       this.identifier.Length = 0;
       this.endPos--;
       this.startPos = this.endPos;
       if (!this.IsIdentifierStartChar(chr))
         this.HandleError(Error.ExpectedIdentifier);
       else{
         this.ScanIdentifier();
         if (this.PreprocessorDefinedSymbols == null){
           this.PreprocessorDefinedSymbols = new Hashtable();
           this.PreprocessorDefinedSymbols["true"] = "true";
         }
         string s = this.GetIdentifierString();
         if (s == "true" || s == "false" || !this.IsIdentifierStartChar(s[0])){
           this.HandleError(Error.ExpectedIdentifier);
           goto skipToEndOfLine;
         }else
           this.PreprocessorDefinedSymbols[s] = null;
       }
       break;
     case "if":
       if (insideExcludedBlock){
         this.endIfCount++;
         this.RestartStateHasChanged = true;
         goto skipToEndOfLine;
       }
       char c = (char)0;
       exclude = !this.ScanPPExpression(ref c);
       if (this.sink != null) {
         if (this.regionCtxStack == null) this.regionCtxStack = new Stack();
         SourceContext regionCtx = this.CurrentSourceContext;
         regionCtx.StartPos = this.PositionOfFirstCharacterOfNextLine(this.endPos);
         regionCtx.EndPos = regionCtx.StartPos;
         regionCtxStack.Push(regionCtx);
       }
       if (!exclude) this.includeCount++;
       this.endIfCount++;
       this.nonExcludedEndIfCount++;
       this.RestartStateHasChanged = true;
       if (this.IsEndLineOrEOF(c, 0)) return exclude;
       break;
     case "elif":
       if (insideExcludedBlock && (this.endIfCount - nonExcludedEndifCount) > 1) goto skipToEndOfLine;
       if (this.elseCount == this.endIfCount){
         //Already found an else
         this.HandleError(Error.UnexpectedDirective);
         goto skipToEndOfLine;
       }
       c = (char)0;
       exclude = !this.ScanPPExpression(ref c);
       if (this.sink != null && this.regionCtxStack != null && this.regionCtxStack.Count > 0) {
         SourceContext startRegionCtx = (SourceContext)regionCtxStack.Pop();
         startRegionCtx.EndPos = this.PositionOfLastCharacterOfPreviousLine(savedStartPos)+1;
         if (startRegionCtx.EndPos > startRegionCtx.StartPos)
           this.sink.AddCollapsibleRegion(startRegionCtx, insideExcludedBlock);
         SourceContext regionCtx = this.CurrentSourceContext;
         regionCtx.StartPos = this.endPos;
         regionCtx.StartPos = this.PositionOfFirstCharacterOfNextLine(this.endPos);
         regionCtx.EndPos = regionCtx.StartPos;
         regionCtxStack.Push(regionCtx);
       }
       if (this.includeCount == this.endIfCount){
         //The #if, or a preceding #elif has already been included, hence this block must be excluded regardless of the expression
         exclude = true;
         break;
       }
       if (!exclude){
         this.includeCount++;
         this.RestartStateHasChanged = true;
       }
       if (this.IsEndLineOrEOF(c, 0)) return exclude;
       break;
     case "else":
       if (insideExcludedBlock && (this.endIfCount - nonExcludedEndifCount) > 1) goto skipToEndOfLine;
       if (this.elseCount == this.endIfCount){
         this.HandleError(Error.UnexpectedDirective);
         goto skipToEndOfLine;
       }
       if (this.sink != null && this.regionCtxStack != null && this.regionCtxStack.Count > 0) {
         SourceContext startRegionCtx = (SourceContext)regionCtxStack.Pop();
         startRegionCtx.EndPos = this.PositionOfLastCharacterOfPreviousLine(savedStartPos)+1;
         if (startRegionCtx.EndPos > startRegionCtx.StartPos)
           this.sink.AddCollapsibleRegion(startRegionCtx, insideExcludedBlock);
         SourceContext regionCtx = this.CurrentSourceContext;
         regionCtx.StartPos = this.PositionOfFirstCharacterOfNextLine(this.endPos);
         regionCtx.EndPos = regionCtx.StartPos;
         regionCtxStack.Push(regionCtx);
       }
       this.elseCount++;
       this.RestartStateHasChanged = true;
       if (this.includeCount == this.endIfCount){
         exclude = true;
         break;
       }
       exclude = false;
       this.includeCount++;
       break;
     case "endif":
       if (this.endIfCount <= 0){
         this.endIfCount = 0;
         this.nonExcludedEndIfCount = 0;
         this.RestartStateHasChanged = true;
         this.HandleError(Error.UnexpectedDirective);
         goto skipToEndOfLine;
       }
       bool collapse = false;
       this.endIfCount--;
       if (!insideExcludedBlock || this.nonExcludedEndIfCount > this.endIfCount) this.nonExcludedEndIfCount--;
       if (this.includeCount > this.endIfCount){ //Can only happen if the #if-#else-#elif-#end block itself appears in an included block and has an included part
         this.includeCount = this.endIfCount;
         collapse = true;
       }
       if (this.endIfCount > 0)
         this.elseCount = this.endIfCount-1;
       else{
         this.elseCount = 0;
         collapse = true;
       }
       if (collapse && this.sink != null && this.regionCtxStack != null && this.regionCtxStack.Count > 0) {
         SourceContext startRegionCtx = (SourceContext)regionCtxStack.Pop();
         startRegionCtx.EndPos = this.PositionOfLastCharacterOfPreviousLine(savedStartPos)+1;
         if (startRegionCtx.EndPos > startRegionCtx.StartPos)
           this.sink.AddCollapsibleRegion(startRegionCtx, insideExcludedBlock);
         if (this.regionCtxStack.Count == 0) this.regionCtxStack = null;
       }
       this.RestartStateHasChanged = true;
       break;
     case "line":
       if (insideExcludedBlock) goto skipToEndOfLine;
       c = this.SkipBlanks();
       int lnum = -1;
       if ('0' <= c && c <= '9'){
         this.startPos = --this.endPos;
         while ('0' <= (c = this.GetChar(++this.endPos)) && c <= '9');
         try{
           lnum = int.Parse(this.GetTokenSource(), CultureInfo.InvariantCulture);
           if (lnum <= 0){
             this.startPos = this.endPos;
             this.HandleError(Error.InvalidLineNumber);
             goto skipToEndOfLine;
           }else if (this.IsEndLineOrEOF(c, 0))
             goto setLineInfo;
         }catch(OverflowException){
           this.startPos++;
           this.HandleError(Error.IntOverflow);
           goto skipToEndOfLine;
         }
       }else{
         this.startPos = this.endPos-1;
         this.ScanIdentifier();
         if (this.startPos != this.endPos-1){
           string str = this.GetIdentifierString();
           if (str == "default"){
             this.document = this.originalDocument;
             break;
           }
           if (str == "hidden" && this.document != null){
             this.document = new Document(this.document.Name, this.document.LineNumber, this.document.Text, this.document.DocumentType, this.document.Language, this.document.LanguageVendor);
             this.document.Hidden = true;
             break;
           }
         }
         this.HandleError(Error.InvalidLineNumber);
         goto skipToEndOfLine;
       }
       c = this.SkipBlanks();
       this.startPos = this.endPos-1;
       if (c == '/'){
         if (this.GetChar(this.endPos) == '/'){
           this.endPos--;
           goto setLineInfo;
         }else{
           this.startPos = this.endPos-1;
           this.HandleError(Error.EndOfPPLineExpected);
           goto skipToEndOfLine;
         }
       }
       if (c == '"'){
         while ((c = this.GetChar(this.endPos++)) != '"' && !this.IsEndLineOrEOF(c, 0));
         if (c != '"'){
           this.HandleError(Error.MissingPPFile);
           goto skipToEndOfLine;
         }
         this.startPos++;
         this.endPos--;
         string filename = this.GetTokenSource();
         this.endPos++;
         if (this.document != null)
           this.document = new Document(filename, 1, this.document.Text, this.document.DocumentType, this.document.Language, this.document.LanguageVendor);
       }else if (!this.IsEndLineOrEOF(c, 0)){
         this.HandleError(Error.MissingPPFile);
         goto skipToEndOfLine;
       }else
         goto setLineInfo;
       c = this.SkipBlanks();
       this.startPos = this.endPos-1;
       if (c == '/'){
         if (this.GetChar(this.endPos) == '/'){
           this.endPos--;
           goto setLineInfo;
         }else{
           this.startPos = this.endPos-1;
           this.HandleError(Error.EndOfPPLineExpected);
           goto skipToEndOfLine;
         }
       }
     setLineInfo:
       Document doc = this.document;
       if (doc != null){
         this.document = doc = new Document(doc.Name, 1, doc.Text, doc.DocumentType, doc.Language, doc.LanguageVendor);
         int offset = lnum - doc.GetLine(this.startPos);
         doc.LineNumber = offset;
       }
       if (this.IsEndLineOrEOF(c, 0)) return exclude;
       break;
     case "error":
       if (insideExcludedBlock) goto skipToEndOfLine;
       this.SkipBlanks();
       this.startPos = --this.endPos;
       this.ScanString((char)0);
       this.HandleError(Error.ErrorDirective, this.unescapedString);
       break;
     case "warning":
       if (insideExcludedBlock) goto skipToEndOfLine;
       this.SkipBlanks();
       this.startPos = --this.endPos;
       this.ScanString((char)0);
       this.HandleError(Error.WarningDirective, this.unescapedString);
       break;
     case "region":
       if (insideExcludedBlock) goto skipToEndOfLine;
       this.regionCount++;
       if (this.sink != null){
         if (this.regionCtxStack == null) this.regionCtxStack = new Stack();
         SourceContext regionCtx = this.CurrentSourceContext;
         regionCtx.StartPos = this.PositionOfFirstCharacterOfNextLine(this.endPos);
         regionCtx.StartPos = this.PositionOfLastCharacterOfPreviousLine(regionCtx.StartPos)+1;
         regionCtxStack.Push(regionCtx);
       }
       goto skipToEndOfLine;
     case "endregion":
       if (insideExcludedBlock) goto skipToEndOfLine;
       if (this.regionCount <= 0)
         this.HandleError(Error.UnexpectedDirective);
       else
         this.regionCount--;
       if (this.sink != null && this.regionCtxStack != null && this.regionCtxStack.Count > 0){
         SourceContext startRegionCtx = (SourceContext)regionCtxStack.Pop();
         startRegionCtx.EndPos = this.endPos;
         this.sink.AddCollapsibleRegion(startRegionCtx, true);
         if (this.regionCtxStack.Count == 0) this.regionCtxStack = null;
       }
       goto skipToEndOfLine;
     case "pragma":
       this.SkipBlanks();
       this.startPos = --this.endPos;
       this.ScanIdentifier();
       string identString = this.GetIdentifierString();
       if (identString != "warning") {
         this.HandleError(Error.UnexpectedDirective);
         goto skipToEndOfLine;
       }
       this.SkipBlanks();
       this.startPos = --this.endPos;
       this.ScanIdentifier();
       identString = this.GetIdentifierString();
       bool disable;
       if (identString == "disable") {
         disable = true;
       } else if (identString == "restore") {
         disable = false;
       } else {
         this.HandleError(Error.ErrorDirective);
         goto skipToEndOfLine;
       }
       while (true) {
         this.SkipBlanks();
         this.startPos = --this.endPos;
         c = this.GetChar(this.endPos);
         if (this.IsEndLineOrEOF(c, 0)) return exclude; 
         if (c < '0' || c > '9') {
           this.HandleError(Error.IntegralTypeValueExpected);
           goto skipToEndOfLine;
         }
         while ('0' <= (c = this.GetChar(++this.endPos)) && c <= '9') ;
         int warnNum;
         try {
           warnNum = int.Parse(this.GetTokenSource(), CultureInfo.InvariantCulture);
           if (warnNum <= 0) {
             this.startPos = this.endPos;
             this.HandleError(Error.Warning);
             goto skipToEndOfLine;
           }
         } catch (OverflowException) {
           this.startPos++;
           this.HandleError(Error.IntOverflow);
           goto skipToEndOfLine;
         }
         PragmaInfo pragmaInfo = (PragmaInfo)this.pragmaInformation[warnNum];
         this.pragmaInformation[warnNum] = new PragmaInfo(this.CurrentSourceContext.StartLine, disable, pragmaInfo);
         if (this.SkipBlanks() != ',')
           break;
       }
       goto skipToEndOfLine;
     default:
       if (insideExcludedBlock) goto skipToEndOfLine;
       this.HandleError(Error.PPDirectiveExpected);
       goto skipToEndOfLine;
   }
   char ch = this.SkipBlanks();
   if (this.IsEndLineOrEOF(ch, 0)) return exclude;
   if (ch == '/' && (ch = this.GetChar(this.endPos++)) == '/') goto skipToEndOfLine;
   this.startPos = this.endPos-1;
   this.HandleError(Error.EndOfPPLineExpected);
 skipToEndOfLine:
   this.SkipSingleLineComment();
   return exclude;
 }