Guest User

Untitled

a guest
Apr 20th, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 23.93 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Specialized;
  4. using System.Diagnostics;
  5. using System.Globalization;
  6. using System.Text;
  7. using DDW.Collections;
  8. using DDW.Enums;
  9. using DDW.Names;
  10.  
  11. namespace DDW
  12. {
  13.     public class Parser
  14.     {
  15.         public static readonly Token EOF = new Token(TokenID.Eof);
  16.         private static readonly Modifier[] modMap;
  17.         private static readonly byte[] precedence;
  18.         private static readonly Dictionary<string, PreprocessorID> preprocessor;
  19.         public static int ASSOC_LEFT = 1;
  20.         public static int ASSOC_RIGHT;
  21.         public static int no_name_index;
  22.         public static byte PRECEDENCE_MULTIPLICcIVE = 0x7f;
  23.  
  24.         public static byte PRECEDENCE_PRIMARY = 0x90;
  25.         public static byte PRECEDENCE_UNARY = 0x80;
  26.         public static char[] QualifiedIdentifierDelimiters = new[] { '.' };
  27.         private readonly string currentFileName = string.Empty;
  28.  
  29.         /// <summary>
  30.         /// all parsed errors are stored in this list
  31.         /// </summary>
  32.         public readonly List<Error> Errors = new List<Error>();
  33.  
  34.         /// <summary>
  35.         /// accessed by <see cref="ParseLocalDeclaration"/>
  36.         /// </summary>
  37.         private Stack<BlockStatement> blockStack;
  38.  
  39.         /// <summary>
  40.         /// This dictionary stores all parsed constructed types.
  41.         /// The key is the full qualified namespace plus the unique identifier of the type
  42.         /// ( <see cref="ConstructedTypeNode.GenericIdentifier"/> ).
  43.         /// I.e. : namespace1.namespace2.type
  44.         ///
  45.         /// This field has two objectives :
  46.         ///     1. control the unicity of each type between all parsed files.
  47.         ///     2. grabs together partial class defined in different files.
  48.         /// </summary>
  49.         private Dictionary<string, ConstructedTypeNode> constructedTypes;
  50.  
  51.         private CompilationUnitNode cu;
  52.         private NodeCollection<AttributeNode> curAttributes;
  53.         private InterfaceNode curInterface;
  54.  
  55.         /// <summary>
  56.         /// used by ParseYieldStatement to check that an iterator is really iterator :
  57.         /// A class which inherits from the IIterator interface could be iterator and it could be not iterator.
  58.         /// It depends on its return type.
  59.         /// </summary>
  60.         private IIterator curIterator;
  61.  
  62.         /// <summary>
  63.         /// many syntax checks need to access method parameter list
  64.         /// </summary>
  65.         private MethodNode curMethod;
  66.  
  67.         private Modifier curmods;
  68.         private OperatorNode curOperator;
  69.         private string currentDocComment = string.Empty;
  70.  
  71.         private ParseStateCollection curState;
  72.         private Token curtok;
  73.  
  74.         private Dictionary<string, Constraint> curTypeParameterConstraints;
  75.  
  76.         /// <summary>
  77.         /// can not be Dictionary<string, TypeParameterNode> because in the case
  78.         /// class test : i<X,X>, the keys 'X' will be duplicated
  79.         /// </summary>
  80.         private List<TypeParameterNode> curTypeParameters;
  81.  
  82.         private Stack<ExpressionNode> exprStack;
  83.  
  84.         /// <summary>
  85.         /// stores all parsed generic type
  86.         /// </summary>
  87.         private List<IGeneric> genericList;
  88.  
  89.         /// <summary>
  90.         /// to travel information from the try to catch to notify it that the try has a 'yield return'
  91.         /// </summary>
  92.         private bool hasYieldReturnInTry;
  93.  
  94.         private bool inPPDirective;
  95.         /// <summary>
  96.         /// this flag is set when we enter in an anonymous delegate declaration
  97.         /// this is an integer because we can declare anonymous delegate in anonymous delegate ...
  98.         /// </summary>
  99.         private int isAnonymous;
  100.  
  101.         private int isCatch;
  102.         private int isFinally;
  103.         private bool isLocalConst;
  104.         private bool isNewStatement;
  105.  
  106.         /// <summary>
  107.         /// this flag is set when we enter in an try, catch or finally block
  108.         /// this is an integer because we can declare try another try ...
  109.         /// </summary>
  110.         private int isTry;
  111.  
  112.         /// <summary>
  113.         /// this flag is set when we enter in an unsafe block
  114.         /// this is an integer because we can declare unsafe block in unsafe block ...
  115.         ///
  116.         /// It is usefull to travel the unsafe state in child block :
  117.         /// for example, a block declared in an unsafe block, i unsafe, so
  118.         /// it inherits the unsafe state of his parent block
  119.         /// </summary>
  120.         private int isUnsafe;
  121.  
  122.         //iterator constant
  123.         /// <summary>
  124.         /// this field is used to keep a list of interface that made a method an iterator
  125.         /// </summary>
  126.         private StringCollection iteratorsClass;
  127.  
  128.         private int lineCount = 1;
  129.         private bool mayBeLocalDecl;
  130.         private Stack<NamespaceNode> namespaceStack;
  131.         private bool nextIsPartial;
  132.  
  133.         /// <summary>
  134.         /// This is always the following token of the curtok.
  135.         /// Don't use it for lookahead though, as it may be a whitespace, newline, comment or hash token!!!
  136.         /// </summary>
  137.         private LinkedListNode<Token> nextTokNode;
  138.  
  139.         private bool ppCondition;
  140.         private List<string> strings;
  141.         private TokenCollection tokens;
  142.         private Stack<ClassNode> typeStack;
  143.  
  144.         static Parser()
  145.         {
  146.             // all default to zero
  147.             modMap = new Modifier[0xFF];
  148.  
  149.             modMap[(int)TokenID.New] = Modifier.New;
  150.             modMap[(int)TokenID.Public] = Modifier.Public;
  151.             modMap[(int)TokenID.Protected] = Modifier.Protected;
  152.             modMap[(int)TokenID.Internal] = Modifier.Internal;
  153.             modMap[(int)TokenID.Private] = Modifier.Private;
  154.             modMap[(int)TokenID.Abstract] = Modifier.Abstract;
  155.             modMap[(int)TokenID.Sealed] = Modifier.Sealed;
  156.             modMap[(int)TokenID.Static] = Modifier.Static;
  157.             modMap[(int)TokenID.Virtual] = Modifier.Virtual;
  158.             modMap[(int)TokenID.Override] = Modifier.Override;
  159.             modMap[(int)TokenID.Extern] = Modifier.Extern;
  160.             modMap[(int)TokenID.Readonly] = Modifier.Readonly;
  161.             modMap[(int)TokenID.Volatile] = Modifier.Volatile;
  162.             modMap[(int)TokenID.Ref] = Modifier.Ref;
  163.             modMap[(int)TokenID.Out] = Modifier.Out;
  164.             //          modMap[(int)TokenID.Assembly] = Modifier.Assembly;
  165.             //          modMap[(int)TokenID.Field] = Modifier.Field;
  166.             modMap[(int)TokenID.Event] = Modifier.Event;
  167.             //          modMap[(int)TokenID.Method] = Modifier.Method;
  168.             //          modMap[(int)TokenID.Param] = Modifier.Param;
  169.             //          modMap[(int)TokenID.Property] = Modifier.Property;
  170.             modMap[(int)TokenID.Return] = Modifier.Return;
  171.             //          modMap[(int)TokenID.Type] = Modifier.Type;
  172.             //            modMap[(int)TokenID.Partial] = Modifier.Partial;
  173.             modMap[(int)TokenID.Unsafe] = Modifier.Unsafe;
  174.             modMap[(int)TokenID.Fixed] = Modifier.Fixed;
  175.  
  176.             // all default to zero
  177.             precedence = new byte[0xFF];
  178.  
  179.             // these start at 80 for no particular reason
  180.             precedence[(int)TokenID.LBracket] = PRECEDENCE_PRIMARY;
  181.             precedence[(int)TokenID.Dot] = PRECEDENCE_PRIMARY;
  182.             precedence[(int)TokenID.MinusGreater] = PRECEDENCE_PRIMARY;
  183.  
  184.  
  185.             precedence[(int)TokenID.LParen] = PRECEDENCE_UNARY;     // 0x80
  186.             precedence[(int)TokenID.Not] = PRECEDENCE_UNARY;
  187.             precedence[(int)TokenID.Tilde] = PRECEDENCE_UNARY;
  188.             precedence[(int)TokenID.PlusPlus] = PRECEDENCE_UNARY;
  189.             precedence[(int)TokenID.MinusMinus] = PRECEDENCE_UNARY;
  190.             precedence[(int)TokenID.Star] = PRECEDENCE_MULTIPLICcIVE; // 0x7f
  191.             precedence[(int)TokenID.Slash] = PRECEDENCE_MULTIPLICcIVE;
  192.             precedence[(int)TokenID.Percent] = PRECEDENCE_MULTIPLICcIVE;
  193.             precedence[(int)TokenID.Plus] = 0x7E;
  194.             precedence[(int)TokenID.Minus] = 0x7E;
  195.             precedence[(int)TokenID.ShiftLeft] = 0x7D;
  196.             precedence[(int)TokenID.ShiftRight] = 0x7D;
  197.             precedence[(int)TokenID.Less] = 0x7C;
  198.             precedence[(int)TokenID.Greater] = 0x7C;
  199.             precedence[(int)TokenID.LessEqual] = 0x7C;
  200.             precedence[(int)TokenID.GreaterEqual] = 0x7C;
  201.             precedence[(int)TokenID.Is] = 0x7C;
  202.             precedence[(int)TokenID.As] = 0x7C;
  203.             precedence[(int)TokenID.EqualEqual] = 0x7B;
  204.             precedence[(int)TokenID.NotEqual] = 0x7B;
  205.             precedence[(int)TokenID.BAnd] = 0x7A;
  206.             precedence[(int)TokenID.BXor] = 0x79;
  207.             precedence[(int)TokenID.BOr] = 0x78;
  208.             precedence[(int)TokenID.And] = 0x77;
  209.             precedence[(int)TokenID.Or] = 0x76;
  210.             precedence[(int)TokenID.QuestionQuestion] = 0x75;
  211.             precedence[(int)TokenID.Question] = 0x74;
  212.  
  213.             precedence[(int)TokenID.Equal] = 0x73;
  214.             precedence[(int)TokenID.PlusEqual] = 0x73;
  215.             precedence[(int)TokenID.MinusEqual] = 0x73;
  216.             precedence[(int)TokenID.StarEqual] = 0x73;
  217.             precedence[(int)TokenID.SlashEqual] = 0x73;
  218.             precedence[(int)TokenID.PercentEqual] = 0x73;
  219.             precedence[(int)TokenID.BAndEqual] = 0x73;
  220.             precedence[(int)TokenID.BOrEqual] = 0x73;
  221.             precedence[(int)TokenID.BXorEqual] = 0x73;
  222.             precedence[(int)TokenID.ShiftLeftEqual] = 0x73;
  223.             precedence[(int)TokenID.ShiftRightEqual] = 0x73;
  224.  
  225.  
  226.             preprocessor = new Dictionary<string, PreprocessorID>();
  227.  
  228.             preprocessor.Add("define", PreprocessorID.Define);
  229.             preprocessor.Add("undef", PreprocessorID.Undef);
  230.             preprocessor.Add("if", PreprocessorID.If);
  231.             preprocessor.Add("elif", PreprocessorID.Elif);
  232.             preprocessor.Add("else", PreprocessorID.Else);
  233.             preprocessor.Add("endif", PreprocessorID.Endif);
  234.             preprocessor.Add("line", PreprocessorID.Line);
  235.             preprocessor.Add("error", PreprocessorID.Error);
  236.             preprocessor.Add("warning", PreprocessorID.Warning);
  237.             preprocessor.Add("region", PreprocessorID.Region);
  238.             preprocessor.Add("endregion", PreprocessorID.Endregion);
  239.             preprocessor.Add("pragma", PreprocessorID.Pragma);
  240.  
  241.         }
  242.  
  243.  
  244.         public Parser(string currentFileName)
  245.         {
  246.             this.currentFileName = currentFileName;
  247.         }
  248.  
  249.         #region Name Resolution
  250.  
  251.         private readonly Context currentContext = new Context();
  252.         private readonly NameResolutionTable nameTable = new NameResolutionTable();
  253.  
  254.         private void EnterNamespace(string qualifiedName)
  255.         {
  256.             string[] nameParts = qualifiedName.Split(Type.Delimiter);
  257.  
  258.             for (int i = 0; i < nameParts.Length; i++)
  259.             {
  260.                 nameTable.AddIdentifier(new NamespaceName(nameParts[i], currentContext));
  261.                 currentContext.Enter(nameParts[i], true);
  262.             }
  263.         }
  264.  
  265.         private void LeaveNamespace(string qualifiedName)
  266.         {
  267.             int index = -1;
  268.  
  269.             while ((index = qualifiedName.IndexOf(Type.Delimiter, index + 1)) != -1)
  270.             {
  271.                 currentContext.Leave();
  272.             }
  273.  
  274.             currentContext.Leave();
  275.         }
  276.  
  277.         private static NameVisibilityRestriction ToVisibilityRestriction(Modifier modifier)
  278.         {
  279.             Modifier relevantMods = modifier & Modifier.Accessibility;
  280.             NameVisibilityRestriction restriction = NameVisibilityRestriction.Self;
  281.  
  282.             if ((relevantMods & Modifier.Protected) != Modifier.Empty)
  283.             {
  284.                 restriction = NameVisibilityRestriction.Family;
  285.             }
  286.  
  287.             if (((relevantMods & Modifier.Internal) != Modifier.Empty) ||
  288.                 ((relevantMods & Modifier.Public) != Modifier.Empty))
  289.             {
  290.                 restriction = NameVisibilityRestriction.Everyone;
  291.             }
  292.  
  293.             return restriction;
  294.         }
  295.         #endregion
  296.  
  297.         public ParseStateCollection CurrentState
  298.         {
  299.             get { return curState; }
  300.         }
  301.  
  302.  
  303.         public CompilationUnitNode Parse(TokenCollection tokens, List<string> strings)
  304.         {
  305.             this.tokens = tokens;
  306.             this.strings = strings;
  307.             curmods = Modifier.Empty;
  308.             curAttributes = new NodeCollection<AttributeNode>();
  309.             curTypeParameters = new List<TypeParameterNode>();
  310.             curTypeParameterConstraints = new Dictionary<string, Constraint>();
  311.  
  312.             blockStack = new Stack<BlockStatement>();
  313.  
  314.             curState = new ParseStateCollection();
  315.  
  316.             cu = new CompilationUnitNode();
  317.             namespaceStack = new Stack<NamespaceNode>();
  318.             namespaceStack.Push(cu.DefaultNamespace);
  319.             typeStack = new Stack<ClassNode>();
  320.             genericList = new List<IGeneric>();
  321.             constructedTypes = new Dictionary<string, ConstructedTypeNode>();
  322.  
  323.             iteratorsClass = new StringCollection();
  324.  
  325.             iteratorsClass.Add("IEnumerator");
  326.             iteratorsClass.Add("IEnumerable");
  327.             iteratorsClass.Add("Collections.IEnumerator");
  328.             iteratorsClass.Add("Collections.IEnumerable");
  329.             iteratorsClass.Add("System.Collections.IEnumerator");
  330.             iteratorsClass.Add("System.Collections.IEnumerable");
  331.  
  332.             iteratorsClass.Add("IEnumerator<>");
  333.             iteratorsClass.Add("IEnumerable<>");
  334.             iteratorsClass.Add("Generic.IEnumerator<>");
  335.             iteratorsClass.Add("Generic.IEnumerable<>");
  336.             iteratorsClass.Add("Collections.Generic.IEnumerator<>");
  337.             iteratorsClass.Add("Collections.Generic.IEnumerable<>");
  338.             iteratorsClass.Add("System.Collections.Generic.IEnumerator<>");
  339.             iteratorsClass.Add("System.Collections.Generic.IEnumerable<>");
  340.  
  341.             exprStack = new Stack<ExpressionNode>();
  342.  
  343.             // begin parse
  344.             nextTokNode = tokens.First;
  345.             Advance();
  346.             try
  347.             {
  348.                 ParseNamespaceOrTypes();
  349.             }
  350.             catch
  351.             {
  352.                 Console.WriteLine("Crashed for token: " + curtok + " at line " + curtok.Line + " column " + curtok.Col);
  353.                 //throw;
  354.                 return cu;
  355.             }
  356.  
  357.             cu.NameTable = nameTable;
  358.  
  359.             return cu;
  360.         }
  361.  
  362.         private void ParseNamespaceOrTypes()
  363.         {
  364.             while (!curtok.Equals(EOF))
  365.             {
  366.                 // todo: account for assembly attributes
  367.                 ParsePossibleAttributesAndDocComment(true);
  368.                 if (curAttributes.Count > 0)
  369.                 {
  370.                     for (int i = 0; i < curAttributes.Count; ++i)
  371.                     {
  372.                         AttributeNode an = curAttributes[i];
  373.                         if ((an.Modifiers & Modifier.Assembly) == Modifier.Assembly
  374.                             || (an.Modifiers & Modifier.Module) == Modifier.Module)
  375.                         {
  376.                             cu.DefaultNamespace.Attributes.Add(an);
  377.                             curAttributes.RemoveAt(i);
  378.                             i--;
  379.                         }
  380.                     }
  381.                     //curAttributes.Clear();
  382.                 }
  383.  
  384.                 // can be usingDirectives, globalAttribs, or NamespaceMembersDecls
  385.                 // NamespaceMembersDecls include namespaces, class, struct, interface, enum, delegate
  386.                 switch (curtok.ID)
  387.                 {
  388.                     case TokenID.Using:
  389.                         // using directive
  390.                         ParseUsingDirectives();
  391.                         break;
  392.  
  393.                     case TokenID.New:
  394.                     case TokenID.Public:
  395.                     case TokenID.Protected:
  396.                     case TokenID.Internal:
  397.                     case TokenID.Private:
  398.                     case TokenID.Abstract:
  399.                     case TokenID.Sealed:
  400.                     case TokenID.Static:
  401.                     case TokenID.Unsafe:
  402.                         //parseTypeModifier();
  403.                         curmods |= modMap[(int)curtok.ID];
  404.                         Advance();
  405.                         break;
  406.  
  407.                     case TokenID.Namespace:
  408.                         ParseNamespace();
  409.                         break;
  410.  
  411.                     case TokenID.Class:
  412.                         ParseClass();
  413.                         break;
  414.  
  415.                     case TokenID.Struct:
  416.                         ParseStruct();
  417.                         break;
  418.  
  419.                     case TokenID.Interface:
  420.                         ParseInterface();
  421.                         break;
  422.  
  423.                     case TokenID.Enum:
  424.                         ParseEnum();
  425.                         break;
  426.  
  427.                     case TokenID.Delegate:
  428.                         ParseDelegate();
  429.                         break;
  430.  
  431.                     case TokenID.Semi:
  432.                         Advance();
  433.                         break;
  434.                     case TokenID.Extern:
  435.                         ParseExternAlias();
  436.                         break;
  437.  
  438.                     case TokenID.Ident:
  439.                         if (strings[curtok.Data] == "partial")
  440.                         {
  441.                             Advance();
  442.  
  443.                             if (curtok.ID != TokenID.Class
  444.                                     && curtok.ID != TokenID.Interface
  445.                                     && curtok.ID != TokenID.Struct)
  446.                             {
  447.                                 RecoverFromError("Only class, struct and interface may be declared partial.",
  448.                                     TokenID.Class, TokenID.Struct, TokenID.Interface);
  449.                             }
  450.                             else
  451.                             {
  452.                                 nextIsPartial = true;
  453.                             }
  454.                             break;
  455.                         }
  456.                         goto default;
  457.  
  458.                     case TokenID.RCurly:
  459.                         return;
  460.  
  461.                     case TokenID.Eof:
  462.                         if (namespaceStack.Count != 1)
  463.                             ReportError("Unexpected EOF", curtok);
  464.                         return;
  465.  
  466.                     default:
  467.                         ReportError("Unexpected token", curtok);
  468.                         return;
  469.                 }
  470.             }
  471.         }
  472.  
  473.         private void ParseExternAlias()
  474.         {
  475.             Advance();  // over extern
  476.             if (curtok.ID != TokenID.Ident || strings[curtok.Data] != "alias")
  477.                 ReportError("Expected 'alias', but found: " + curtok.ID, curtok);
  478.             Advance();  // over alias
  479.  
  480.             ExternAliasDirectiveNode node = new ExternAliasDirectiveNode(curtok);
  481.             node.ExternAliasName = ParseIdentifierOrKeyword(false, false, false, false, false);
  482.  
  483.             namespaceStack.Peek().ExternAliases.Add(node);
  484.         }
  485.  
  486.         private void ParseUsingDirectives()
  487.         {
  488.             do
  489.             {
  490.                 Advance();
  491.                 UsingDirectiveNode node = new UsingDirectiveNode(curtok);
  492.  
  493.                 QualifiedIdentifierExpression nameOrAlias = ParseQualifiedIdentifier(true, false, false);
  494.                 if (curtok.ID == TokenID.Equal)
  495.                 {
  496.                     Advance();
  497.  
  498.                     if (nameOrAlias.Expressions.Count > 1)
  499.                         ReportError("An alias name may not be qualified", nameOrAlias.RelatedToken);
  500.  
  501.                     // an alias could be written like
  502.                     // using alias = path.identifier
  503.                     //
  504.                     // or like
  505.                     // using alias = path.identifier<object>
  506.                     //
  507.                     // it is not possible to know before if this a type or an qualified identifier
  508.                     // so we always parse it as a Qualified expression, and if the result is not a type
  509.                     // we keep only the identifier part
  510.  
  511.                     QualifiedIdentifierExpression target = ParseQualifiedIdentifier(true, false, false);
  512.  
  513.                     if (target.IsType)
  514.                     {
  515.                         node.Target = new TypeNode(target);
  516.                     }
  517.                     else
  518.                     {
  519.                         // it does not mean that this is not a type.
  520.                         // it only means that actually we can not resolve the type
  521.                         // but in a next stage, we will probably resolve it as a type.
  522.                         node.Target = target;
  523.                     }
  524.  
  525.                     node.AliasName = nameOrAlias.Expressions[0] as IdentifierExpression;
  526.                     if (node.AliasName == null)
  527.                     {
  528.                         ReportError("An alias name must be an identifier", nameOrAlias.RelatedToken);
  529.                         node.AliasName = IdentifierExpression.GetErrorIdentifier(nameOrAlias.RelatedToken);
  530.                     }
  531.                 }
  532.                 else
  533.                 {
  534.                     node.Target = nameOrAlias;
  535.                 }
  536.  
  537.                 AssertAndAdvance(TokenID.Semi);
  538.  
  539.                 namespaceStack.Peek().UsingDirectives.Add(node);
  540.  
  541.                 currentContext.AddUsingDirective(node);
  542.  
  543.             } while (curtok.ID == TokenID.Using);
  544.         }
  545.  
  546.         private bool EvalPPExpression(ExpressionNode expr)
  547.         {
  548.             BinaryExpression binExpr = expr as BinaryExpression;
  549.             if (binExpr != null)
  550.             {
  551.                 switch (binExpr.Op)
  552.                 {
  553.                     case TokenID.Or:
  554.                         return EvalPPExpression(binExpr.Left) || EvalPPExpression(binExpr.Right);
  555.                     case TokenID.And:
  556.                         return EvalPPExpression(binExpr.Left) && EvalPPExpression(binExpr.Right);
  557.                     case TokenID.EqualEqual:
  558.                         return EvalPPExpression(binExpr.Left) == EvalPPExpression(binExpr.Right);
  559.                     case TokenID.NotEqual:
  560.                         return EvalPPExpression(binExpr.Left) != EvalPPExpression(binExpr.Right);
  561.                     default:
  562.                         ReportError("Illegal binary preprocessor expression", binExpr.RelatedToken);
  563.                         return false;
  564.                 }
  565.             }
  566.  
  567.             UnaryExpression unExpr = expr as UnaryExpression;
  568.             if (unExpr != null)
  569.             {
  570.                 if (unExpr.Op == TokenID.Not)
  571.                     return !EvalPPExpression(unExpr.Child);
  572.                 ReportError("Illegal unary preprocessor expression", binExpr.RelatedToken);
  573.                 return false;
  574.             }
  575.  
  576.             IdentifierExpression idExpr = expr as IdentifierExpression;
  577.             if (idExpr != null)
  578.                 return cu.PPDefs.ContainsKey(idExpr.Identifier);
  579.  
  580.             BooleanPrimitive boolPrim = expr as BooleanPrimitive;
  581.             if (boolPrim != null)
  582.                 return boolPrim.Value;
  583.  
  584.             ParenthesizedExpression parenExpr = expr as ParenthesizedExpression;
  585.             if (parenExpr != null)
  586.                 return EvalPPExpression(parenExpr.Expression);
  587.  
  588.             ReportError("Illegal preprocessor expression", expr.RelatedToken);
  589.             return false;
  590.         }
  591.  
  592.         private bool SameLine(int oldLine)
  593.         {
  594.             if (curtok.Line != oldLine)
  595.             {
  596.                 ReportError("Unexpected end of line", curtok);
  597.                 return false;
  598.             }
  599.             return true;
  600.         }
  601.  
  602.         private void ParsePreprocessorExpressionSegment(int oldLine)
  603.         {
  604.             int startStackCount = exprStack.Count;
  605.             TokenID startToken = curtok.ID;
  606.             switch (curtok.ID)
  607.             {
  608.                 case TokenID.True:
  609.                     exp
Add Comment
Please, Sign In to add comment