コード例 #1
0
        public void Print(IEnumerable <ILNode> nodes, StringBuilder target, IMessageSink sink = null, ParsingMode mode = null, ILNodePrinterOptions options = null)
        {
            CheckParam.IsNotNull("target", target);
            var p = new Les3Printer(target, sink, options);

            p.Print(nodes);
        }
コード例 #2
0
        public MacroInfo(Symbol @namespace, LexicalMacroAttribute a, LexicalMacro macro, bool deprecateAllNames = false)
            : base(a.Syntax, a.Description, a.Names)
        {
            DeprecatedNames    = a.DeprecatedNames;
            DeprecationMessage = a.DeprecationMessage;

            if (Names.Length == 0 &&
                (a.DeprecatedNames == null || a.DeprecatedNames.Length == 0) &&
                (a.Mode & (MacroMode.MatchEveryCall | MacroMode.MatchEveryLiteral | MacroMode.MatchEveryIdentifier)) == 0)
            {
                Names = new string[1] {
                    macro.Method.Name
                }
            }
            ;

            if (deprecateAllNames)
            {
                DeprecatedNames = (DeprecatedNames ?? EmptyArray <string> .Value).Union(Names).ToArray();
            }

            CheckParam.IsNotNull("macro", macro);
            Namespace = @namespace;
            Macro     = macro;
            Mode      = a.Mode;
        }
コード例 #3
0
ファイル: IMacroContext.cs プロジェクト: sizzles/ecsharp
		public MacroInfo(Symbol @namespace, LexicalMacroAttribute a, LexicalMacro macro)
			: base(a.Syntax, a.Description, a.Names != null && a.Names.Length > 0 ? a.Names : new[] { macro.Method.Name })
		{
			CheckParam.IsNotNull("macro", macro);
			Namespace = @namespace;
			Macro = macro;
			Mode = a.Mode;
		}
コード例 #4
0
ファイル: EcsValidators.cs プロジェクト: sizzles/ecsharp
        /// <summary>Returns true if the specified child of the specified node
        /// can be an implicit child statement, i.e. a child statement that is
        /// not necessarily a braced block, e.g. the second child of a while
        /// loop.</summary>
        /// <remarks>
        /// This method helps the printer decide when a newline should be added
        /// before an unbraced child statement when there are no attributes
        /// dictating whether to add a newline or not.
        /// <para/>
        /// This method only cares about executable parent nodes. It returns
        /// false for class/space and function/property bodies, which are always
        /// braced blocks and therefore get a newline before every child statement
        /// automatically.
        /// </remarks>
        public static bool MayBeImplicitChildStatement(LNode node, int childIndex)
        {
            CheckParam.IsNotNull("node", node);
            if (childIndex < 0)             // target or attributes
            {
                return(false);
            }
            var n = node.Name;

            if (!LNode.IsSpecialName(n.Name))
            {
                return(false);
            }
            if (n == S.Braces)
            {
                return(true);
            }
            if (n == S.Try)
            {
                return(childIndex == 0);
            }
            switch (node.ArgCount)
            {
            case 1:
                if (n == S.Finally)
                {
                    return(true);
                }
                break;

            case 2:
                if (childIndex == 0 ? n == S.DoWhile :
                    n == S.If || n == S.While || n == S.UsingStmt || n == S.Lock || n == S.Switch || n == S.Fixed)
                {
                    return(true);
                }
                break;

            case 3:
                if (childIndex != 0 && n == S.If)
                {
                    return(true);
                }
                if (childIndex == 2 && n == S.ForEach)
                {
                    return(true);
                }
                break;

            case 4:
                if (childIndex == 3 && (n == S.For || n == S.Catch))
                {
                    return(true);
                }
                break;
            }
            return(false);
        }
コード例 #5
0
 public virtual void Reset(IListSource <Token> tokens, ISourceFile file)
 {
     CheckParam.IsNotNull("tokens", tokens);
     CheckParam.IsNotNull("file", file);
     _tokensRoot   = _tokens = tokens;
     _sourceFile   = file;
     F             = new LNodeFactory(file);
     InputPosition = 0;             // reads LT(0)
 }
コード例 #6
0
ファイル: BaseParserForList.cs プロジェクト: dadhi/ecsharp
 /// <summary>Reinitializes the object. This method is called by the constructor.</summary>
 /// <remarks>See the constructor for documentation of the parameters.</remarks>
 protected virtual void Reset(List list, Func <Token, Token> getEofToken, MatchType eof, ISourceFile file, int startIndex = 0)
 {
     CheckParam.IsNotNull <object>("list", list);
     _getEofToken  = getEofToken;
     EOF           = eof;
     _tokenList    = list;
     _listCount    = list.Count;          // to avoid 1st-chance exceptions
     _sourceFile   = file;
     InputPosition = startIndex;
 }
コード例 #7
0
ファイル: UG.cs プロジェクト: sizzles/ecsharp
 /// <summary>
 /// Expands environment variables (e.g. %TEMP%) and @files in a list of
 /// command-line arguments, and adds any options of the form "--opt" or
 /// "--opt=value" to a dictionary.
 /// </summary>
 /// <param name="args">The original arguments to process.</param>
 /// <param name="options">Any long options (arguments that start with "--")
 /// will be added to this dictionary, and removed from <c>args</c>. This
 /// parameter cannot be null.
 ///   By default, long options are not case sensitive. In that case, the
 /// user's option name is converted to lower case.
 /// <para/>
 /// Long options are expected to have the form --ID or --ID=value, where ID
 /// matches the regex "[a-zA-Z_0-9-]+". If there is no "=" or ":", that's
 /// okay too. For example, --Id{foo} is equivalent to --Id={foo}; both yield
 /// in the name-value pair ("id", "{foo}"). If there is no value (no equals
 /// or colon), the value associated with the option is null.</param>
 /// <param name="atFolder">If a parameter has the form @filename, the folder
 /// specified by atFolder will be searched for an options text file with the
 /// user-specified filename, and the contents of the file will be expanded
 /// into the list of arguments (split using SplitCommandLineArguments). The
 /// expanded list can contain new @filenames, which are also processed. To
 /// search in the current directory, use "". The @filename may use an absolute
 /// path, which overrides this folder. To disable @filename expansion, set
 /// this parameter to null. Whether the feature is enabled or disabled,
 /// @filenames are <i>not</i> removed from <c>args</c>, in case you want to
 /// be aware of the filenames afterward.</param>
 /// <param name="shortOptions">A map from one-letter options that start with
 /// "-" rather than "--", to the name of the corresponding long option (this
 /// option can be null to ignore all short options.) For example, if this
 /// contains (<c>'a', "all"</c>), and the input <c>args</c> contains "-a:foo",
 /// the pair ("all", "foo") will be added to <c>options</c>. If a value in
 /// this map is null, the key itself is used. Short options can be combined;
 /// for example <c>-abc:foo</c> is equivalent to <c>-a -b -c:foo</c>. Short
 /// options are always case-sensitive; to define an option that is not case
 /// sensitive, place two entries in the dictionary e.g. ('a', "all") and
 /// ('A', "all"). If the user specifies a short option letter that is not
 /// recognized, the entire command will be ignored and left in args. For
 /// example, if <c>shortOptions</c> contains only ('a', "all") but <c>args</c>
 /// contains "-ab=foo", the command is ignored and left in <c>args</c>.
 /// Rationale: -ab=foo might be a filename.
 /// <para/>
 /// On the other hand, if -a is a valid option then <c>-a123</c> is also
 /// valid even when there is no option called '1'; the number "123" is
 /// treated as an argument to -a. Now, if '1' is a registered short option
 /// but '2' is not, then <c>-a123</c> is equivalent to <c>-a -1=23</c>.
 /// </param>
 /// <param name="twoArgOptions">A set of options in which the argument can
 /// be separated by a space from the option. For example, if the input is
 /// "--out foo.txt" and you want to recognize "foo.txt" as the argument to
 /// "--out", add the string "out" to this set. If you want to treat <i>all</i>
 /// options this way, use <c>InvertibleSet{string}.All</c>. Note:
 /// If the input is "--out:foo bar", "foo" is recognized as the argument to
 /// "--out" and "bar" is left alone, i.e. it is treated as unrelated.
 ///   Short options participate automatically. For example if "-f" means
 /// "--foo", and twoArgOptions contains "foo", then "-f arg" is interpreted
 /// like "--foo=arg".
 /// <para/>
 /// The argument will not be treated as an argument if it starts with a
 /// dash, e.g. in <c>--foo -*</c>, <c>-*</c> will not be treated as an
 /// argument to <c>--foo</c>, even if <c>-*</c> is not a registered option.
 /// </param>
 /// <param name="argLimit">A limit placed on the number of arguments when
 /// expanding @files. Such a file may refer to itself, and this is the only
 /// protection provided against infinite recursive expansion.</param>
 /// <param name="expandEnvVars">If true, environment variable references
 /// such as <c>%TEMP%</c> are expanded by calling the standard method
 /// <see cref="Environment.ExpandEnvironmentVariables"/>.</param>
 /// <param name="caseSensitiveLongOpts">If true, long options are case-
 /// sensitive. By default, long options are not case sensitive.</param>
 /// <remarks>
 /// Two types of options are recognized, short (-s) and long (--long), and
 /// only one argument is supported per option. The documentation is above.
 /// <para/>
 /// You can choose whether to permit duplicate options or not. If you use
 /// a standard <see cref="Dictionary{K,V}"/> to hold the options, an
 /// exception will occur when this method calls Add() to add the duplicate.
 /// The exception is caught, the first ocurrance is kept, and a warning
 /// message is printed to <see cref="MessageSink.Default"/>.
 /// <para/>
 /// To allow duplicates, store options in a different data structure such as
 /// <c>List(KeyValuePair(string, string))</c> or <c>BMultiMap(string,string)</c>.
 /// <para/>
 /// DOS-style slash-options like /foo are not supported. Since Windows
 /// recognizes the forward slash as a path separator, forward-slash options
 /// can be recognized as paths. If you want to recognize them as options
 /// instead, you can preprocess the argument list, replacing every command
 /// that starts with "/" with a "--" command:
 /// <code>
 ///   for (int i = 0; args.Count > i; i++)
 ///     if (args[i].StartsWith("/"))
 ///       args[i] = "--" + args[i].Substring(1);
 /// </code>
 /// <para/>
 /// Globs (e.g. *.txt) are not recognized or expanded, but environment
 /// variables are expanded when <c>expandEnvVars</c> is true.
 /// <para/>
 /// Quote marks are not processed. An argument of <c>"--a"</c>, with quote
 /// marks, is not recognized as an option (these quote marks should be
 /// removed before calling this method, e.g.
 /// <see cref="G.SplitCommandLineArguments"/> handles this.)
 /// </remarks>
 public static void ProcessCommandLineArguments(IList <string> args, ICollection <KeyValuePair <string, string> > options, string atFolder, IDictionary <char, string> shortOptions = null, InvertibleSet <string> twoArgOptions = null, int argLimit = 0xFFFF, bool expandEnvVars = true, bool caseSensitiveLongOpts = false)
 {
     CheckParam.IsNotNull("args", args);
     CheckParam.IsNotNull("options", options);
     for (int i = 0; i < args.Count; i++)
     {
         ProcessArgument(args, i, options, atFolder, shortOptions, twoArgOptions, argLimit, expandEnvVars, caseSensitiveLongOpts);
     }
     args.RemoveAll(s => s == null);
 }
コード例 #8
0
 public virtual void Reset(IListSource <Token> tokens, ISourceFile file, IParsingOptions parsingOptions)
 {
     CheckParam.IsNotNull("tokens", tokens);
     CheckParam.IsNotNull("file", file);
     _tokensRoot    = _tokens = tokens;
     _sourceFile    = file;
     _literalParser = parsingOptions?.LiteralParser ?? EcsLiteralHandlers.Value;
     F                = new LNodeFactory(file);
     InputPosition    = 0;          // reads LT(0)
     _tentativeErrors = new TentativeState(false);
 }
コード例 #9
0
 protected override void Reset(IList <Token> list, Func <Token, Token> getEofToken, int eof, ISourceFile file, int startIndex = 0)
 {
     if (list is TokenTree)
     {
         // Token trees can come from token literals, and the user of a
         // token tree expects to be able to parse that tree, but this parser
         // expects a flat token list, so we need to flatten the tree again.
         list = ((TokenTree)list).Flatten();
     }
     CheckParam.IsNotNull("file", file);
     base.Reset(list, getEofToken, eof, file, startIndex);
     F = new LNodeFactory(file);
 }
コード例 #10
0
        public BraceMatchingTagger(ITextView textView, ITextBuffer sourceBuffer, IClassifier classifier, IEnumerable <KeyValuePair <char, char> > matchingCharacters)
        {
            CheckParam.IsNotNull("textView", textView);
            CheckParam.IsNotNull("sourceBuffer", sourceBuffer);
            CheckParam.IsNotNull("aggregator", classifier);
            CheckParam.IsNotNull("matchingCharacters", matchingCharacters);

            this.TextView           = textView;
            this.SourceBuffer       = sourceBuffer;
            this.Classifier         = classifier;
            this.MatchingCharacters = matchingCharacters.ToList().AsReadOnly();

            this.TextView.Caret.PositionChanged += Caret_PositionChanged;
            this.TextView.LayoutChanged         += TextView_LayoutChanged;
        }
コード例 #11
0
        /// <summary>Unregisters a language service.</summary>
        /// <param name="service">Service to unregister</param>
        /// <param name="fileExtensions">File extensions affected (null to use the service's own list)</param>
        /// <returns>The number of file extensions unregistered, or 0 if none.</returns>
        /// <remarks>The service for a file extension is not removed unless the given service reference is equal to the registered service.</remarks>
        public static int Unregister(IParsingService service, IEnumerable <string> fileExtensions = null)
        {
            CheckParam.IsNotNull("service", service);
            fileExtensions = fileExtensions ?? service.FileExtensions;
            int oldCount = _registeredLanguages.Count;

            foreach (var fileExt in fileExtensions)
            {
                if (_registeredLanguages.TryGetValue(fileExt, null) == service)
                {
                    _registeredLanguages = _registeredLanguages.Without(fileExt);
                }
            }
            return(oldCount - _registeredLanguages.Count);
        }
コード例 #12
0
        /// <summary>Registers a parsing service.</summary>
        /// <param name="service">Service to register.</param>
        /// <param name="fileExtensions">File extensions affected (null to use the service's own list)</param>
        /// <returns>The number of new file extensions registered, or 0 if none.</returns>
        /// <remarks>This method does not replace existing registrations.</remarks>
        public static int Register(IParsingService service, IEnumerable <string> fileExtensions = null)
        {
            CheckParam.IsNotNull("service", service);
            int oldCount = _registeredLanguages.Count;

            foreach (var fileExt_ in fileExtensions ?? service.FileExtensions)
            {
                var fileExt = fileExt_;                 // make writable
                if (fileExt.StartsWith("."))
                {
                    fileExt = fileExt.Substring(1);
                }
                _registeredLanguages = _registeredLanguages.With(fileExt, service, false);
            }
            return(_registeredLanguages.Count - oldCount);
        }
コード例 #13
0
        /// <summary>Given a normal operator symbol like <c>(Symbol)"'++"</c>, gets
        /// the suffix form of the name, such as <c>(Symbol)"'suf++"</c>.</summary>
        /// <remarks>op must be a Symbol, but the parameter has type object to avoid casting Token.Value in the parser.</remarks>
        public Symbol ToSuffixOpName(object symbol)
        {
            CheckParam.IsNotNull(nameof(symbol), symbol);

            _suffixOpNames = _suffixOpNames ?? new Dictionary <object, Symbol>();
            Symbol name;

            if (_suffixOpNames.TryGetValue(symbol, out name))
            {
                return(name);
            }

            CheckParam.Arg(nameof(symbol), symbol.ToString().StartsWith("'"), symbol);

            var was = symbol.ToString();

            return(_suffixOpNames[symbol] = GSymbol.Get("'suf" + symbol.ToString().Substring(1)));
        }
コード例 #14
0
 /// <summary>Reinitializes BaseLexer, as if you called the constructor again.</summary>
 protected virtual void Reset(ICharSource source, string fileName = "", int inputPosition = 0, bool newSourceFile = true)
 {
     CheckParam.IsNotNull("source", source);
     _source       = source;
     _fileName     = fileName;
     _block        = UString.Empty;
     InputPosition = inputPosition;
     _lineNumber   = 1;
     _lineStartAt  = inputPosition;
     if (newSourceFile)
     {
         _sourceFile = new LexerSourceFile(source, fileName);
     }
     else
     {
         _sourceFile = null;
     }
 }
コード例 #15
0
 /// <summary>Reinitializes the object. This method is called by the constructor.</summary>
 /// <remarks>
 /// See the constructor for documentation of the parameters.
 /// <para/>
 /// This method can be used to avoid memory allocations when you
 /// need to parse many small strings in a row. If that's your goal, you
 /// should set the <c>newSourceFile</c> parameter to false if possible.</remarks>
 public virtual void Reset(CharSrc chars, string fileName = "", int inputPosition = 0, bool newSourceFile = true)
 {
     CheckParam.IsNotNull <object>("source", chars);
     _charSource   = chars;
     _fileName     = fileName;
     _block        = UString.Empty;
     InputPosition = inputPosition;
     _lineNumber   = 1;
     _lineStartAt  = inputPosition;
     if (newSourceFile)
     {
         _sourceFile = new LexerSourceFile <CharSrc>(chars, fileName);
     }
     else
     {
         _sourceFile = null;
     }
 }
コード例 #16
0
ファイル: LiteralHandlerTable.cs プロジェクト: dadhi/ecsharp
        /// <summary>Searches <see cref="Printers"/> for a printer for the value and uses it
        /// to convert the value to a string. When a printer can be found both by type marker
        /// Symbol and by Type, the printer for the matching type marker is used (takes priority).
        /// The complete search order is (1) type marker (if any), (2) exact type, (3) base
        /// classes and (4) interfaces, in that order.</summary>
        /// <param name="literal">A literal that you want to convert to a string.</param>
        /// <returns>Either the type marker for the literal, or an error message.
        /// On return, the string form of the literal is appended to the StringBuilder.
        /// If an error occurs, it is possible that some kind of output was added to
        /// the StringBuilder anyway.</returns>
        /// <remarks>
        /// Note: this uses `Type.GetInterfaces` to obtain the list of interfaces, and this
        /// list is officially not "in a particular order". It appears that the list is
        /// constructed with some kind of depth-first search, so in simple cases derived
        /// interfaces are searched before base interfaces, but if there are "diamonds" in
        /// the interface hierarchy then it will not be uncommon for a lower-level interface
        /// to be checked before a higher-level one. Sorry.
        /// <para/>
        /// If a printer returns an error, this method tries to find other printers that might
        /// be able to print the value. If no printer succeeds, the <i>first</i> error that
        /// occurred is returned.
        /// <para/>
        /// When the literal is null and there is no printer associated with literal.TypeMarker,
        /// this funtion produces no output and returns literal.TypeMarker.
        /// <para/>
        /// On success, the return value indicates which type marker is recommended based
        /// on the data type of the literal. This is not guaranteed to match the TypeMarker
        /// originally stored in the literal. It is recommended that language printers
        /// use the type marker stored in the literal (regardless of what this method
        /// returns) unless <c>literal.TypeMarker == null</c>.
        /// </remarks>
        public Either <Symbol, ILogMessage> TryPrint(ILNode literal, StringBuilder sb)
        {
            CheckParam.IsNotNull(nameof(sb), sb);
            ILogMessage firstError = null;

            var tm = literal.TypeMarker;

            if (tm != null && TryPrint(literal, tm, sb, ref tm, ref firstError))
            {
                return(tm);
            }

            if (literal.Value == null)
            {
                return(tm);
            }

            Type type = literal.Value.GetType();

            if (TryPrint(literal, type, sb, ref tm, ref firstError))
            {
                return(tm);
            }

            for (var type2 = type; type2.BaseType != null; type2 = type2.BaseType)
            {
                var @base = type2.BaseType;
                if (TryPrint(literal, @base, sb, ref tm, ref firstError))
                {
                    return(tm);
                }
            }
            foreach (var iface in type.GetInterfaces())
            {
                if (TryPrint(literal, iface, sb, ref tm, ref firstError))
                {
                    return(tm);
                }
            }

            return(new Either <Symbol, ILogMessage>(firstError ??
                                                    new LogMessage(Severity.Error, literal,
                                                                   "There is no printer for type '{0}'".Localized(literal.Value.GetType()))));
        }
コード例 #17
0
        private static bool IsInCommentOrLiteral(IClassifier classifier, SnapshotPoint point, PositionAffinity affinity)
        {
            CheckParam.IsNotNull("aggregator", classifier);

            // TODO: handle affinity
            SnapshotSpan span = new SnapshotSpan(point, 1);

            var classifications = classifier.GetClassificationSpans(span);
            var relevant        = classifications.FirstOrDefault(classificationSpan => classificationSpan.Span.Contains(point));

            if (relevant == null || relevant.ClassificationType == null)
            {
                return(false);
            }

            var @class = relevant.ClassificationType;

            return(@class.IsOfType(PredefinedClassificationTypeNames.Comment) ||
                   @class.IsOfType(PredefinedClassificationTypeNames.Literal) ||
                   @class.IsOfType(PredefinedClassificationTypeNames.String) ||
                   @class.IsOfType(PredefinedClassificationTypeNames.Identifier) ||
                   @class.IsOfType("LoycOtherLiteral"));
        }
コード例 #18
0
ファイル: StdNodes.cs プロジェクト: lydonchandra/Loyc
 public StdComplexCallNode(LNode target, RVList <LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default)
     : base(args, range, style)
 {
     CheckParam.IsNotNull("target", target); _target = target;
 }
コード例 #19
0
ファイル: StdNodes.cs プロジェクト: lydonchandra/Loyc
 public StdComplexCallNode(LNode target, RVList <LNode> args, LNode ras)
     : base(args, ras)
 {
     CheckParam.IsNotNull("target", target); _target = target;
 }
コード例 #20
0
 protected override void Reset(IList <Token> list, Token eofToken, ISourceFile file, int startIndex = 0)
 {
     CheckParam.IsNotNull("file", file);
     base.Reset(list, eofToken, file, startIndex);
     F = new LNodeFactory(file);
 }
コード例 #21
0
ファイル: LesPrecedenceMap.cs プロジェクト: feckardt/ecsharp
		protected Precedence FindPrecedence(MMap<object,Precedence> table, object symbol, Precedence @default, bool cacheWordOp, bool les3InfixOp = false)
		{
			// You can see the official rules in the LesPrecedence documentation.
			
			// Rule 1 (for >= <= != ==) is covered by the pre-populated contents 
			// of the table, and the pre-populated table helps interpret other 
			// rules too.
			CheckParam.IsNotNull("symbol", symbol);
			Precedence prec;
			if (table.TryGetValue(symbol, out prec))
				return prec;

			string sym = symbol.ToString();
			if (sym.Length <= 1 || sym[0] != '\'')
				return @default; // empty or non-operator

			// Note: all one-character operators should have been found in the table
			char first = sym[1], last = sym[sym.Length - 1];
			bool isInfix = table == this[OperatorShape.Infix].A;

			if (les3InfixOp)
			{
				// Check for lowercase word prefix
				int i = 1;
				while (first >= 'a' && first <= 'z' || first == '_') {
					if (++i == sym.Length) {
						if (cacheWordOp)
							table[symbol] = P.LowerKeyword;
						return P.LowerKeyword;
					}
					first = sym[i];
				}
				
				if (i + 1 == sym.Length) {
					// After the word is a one-character op. See if it is in the table
					var oneCharOp_ = GSymbol.Get("'" + first);
					if (table.TryGetValue(oneCharOp_, out prec))
						return prec;
				}
			}

			if (isInfix && last == '=') {
				if (first == '=' || first == '!')
					return table[symbol] = P.Compare;
				else
					return table[symbol] = P.Assign;
			}

			var twoCharOp = GSymbol.Get("'" + first + last);
			if (table.TryGetValue(twoCharOp, out prec))
				return table[symbol] = prec;

			var oneCharOp = GSymbol.Get("'" + last);
			if (table.TryGetValue(oneCharOp, out prec))
				return table[symbol] = prec;

			if (isInfix && char.IsLower(first))
				return table[symbol] = P.LowerKeyword;

			// Default precedence is used for anything else
			if (cacheWordOp)
				return table[symbol] = @default;
			return @default;
		}
コード例 #22
0
        protected Precedence FindPrecedence(MMap <object, Precedence> table, object symbol, Precedence @default, bool cacheWordOp)
        {
            // You can see the official rules in the LesPrecedence documentation.

            // Rule 1 (for >= <= != ==) is covered by the pre-populated contents
            // of the table, and the pre-populated table helps interpret other
            // rules too.
            CheckParam.IsNotNull("symbol", symbol);
            Precedence prec;

            if (table.TryGetValue(symbol, out prec))
            {
                return(prec);
            }

            string sym = symbol.ToString();

            if (sym.Length <= 1 || sym[0] != '\'')
            {
                return(P.Other);                // empty or non-operator
            }
            // Note: all one-character operators should have been found in the table
            char first = sym[1], last = sym[sym.Length - 1];

            bool isInfix = table == this[OperatorShape.Infix].A;

            if (isInfix && last == '=')
            {
                if (first == '=' || first == '!')
                {
                    return(table[symbol] = P.Compare);
                }
                else
                {
                    return(table[symbol] = P.Assign);
                }
            }

            var twoCharOp = GSymbol.Get("'" + first + last);

            if (table.TryGetValue(twoCharOp, out prec))
            {
                return(table[symbol] = prec);
            }

            var oneCharOp = GSymbol.Get("'" + last);

            if (table.TryGetValue(oneCharOp, out prec))
            {
                return(table[symbol] = prec);
            }

            if (isInfix && first >= 'A' && first <= 'Z')
            {
                return(table[symbol] = P.UpperWord);
            }

            // Default precedence is used for anything else (lowercase word ops)
            if (cacheWordOp)
            {
                return(table[symbol] = @default);
            }
            return(@default);
        }
コード例 #23
0
ファイル: ReplaceMacro.cs プロジェクト: sizzles/ecsharp
 public static LNode Replace(LNode stmt, Pair <LNode, LNode>[] patterns, out int replacementCount)
 {
     CheckParam.IsNotNull("stmt", stmt);
     return(Replace(new VList <LNode>(stmt), patterns, out replacementCount)[0]);
 }