示例#1
0
文件: ParsedItem.cs 项目: jcaillon/3P
 protected ParsedScopeItem(string name, Token token, ParsedScopeType scopeType)
     : base(name, token)
 {
     ScopeType = scopeType;
     EndBlockPosition = -1;
 }
示例#2
0
文件: Parser.cs 项目: jcaillon/3P
 /// <summary>
 /// Append a token value to the StringBuilder, avoid adding too much spaces and new lines
 /// </summary>
 /// <param name="strBuilder"></param>
 /// <param name="token"></param>
 private void AddTokenToStringBuilder(StringBuilder strBuilder, Token token)
 {
     if ((token is TokenEol || token is TokenWhiteSpace)) {
         if (!_lastTokenWasSpace) {
             _lastTokenWasSpace = true;
             strBuilder.Append(" ");
         }
     } else {
         _lastTokenWasSpace = false;
         strBuilder.Append(token.Value);
     }
 }
示例#3
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// Creates a dynamic function parsed item
        /// </summary>
        private void CreateParsedDynamicFunction(Token tokenFun)
        {
            // info we will extract from the current statement :
            string name = "";
            int state = 0;
            do {
                var token = PeekAt(1); // next token
                if (state == 2) break; // stop after finding the name
                if (token is TokenEos) break;
                if (token is TokenComment) continue;
                switch (state) {
                    case 0:
                        if (token is TokenSymbol && token.Value.Equals("("))
                            state++;
                        break;
                    case 1:
                        // matching proc name (or VALUE)
                        if (token is TokenString) {
                            name = GetTokenStrippedValue(token);
                            state++;
                        }
                        break;
                }
            } while (MoveNext());

            if (state == 0) return;

            AddParsedItem(new ParsedFunctionCall(name, tokenFun, !_functionPrototype.ContainsKey(name)));
        }
示例#4
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// Parses a parameter definition (used in function, class method, class event)
        /// </summary>
        private List<ParsedItem> GetParsedParameters(Token functionToken, StringBuilder parameters)
        {
            // info the parameters
            string paramName = "";
            ParsedAsLike paramAsLike = ParsedAsLike.None;
            string paramPrimitiveType = "";
            string strFlags = "";
            string parameterFor = "";
            bool isExtended = false;
            var parametersList = new List<ParsedItem>();

            int state = 0;
            do {
                var token = PeekAt(1); // next token
                if (token is TokenEos) break;
                if (token is TokenSymbol && (token.Value.Equals(")"))) state = 99;
                if (token is TokenComment) continue;
                switch (state) {
                    case 0:
                        // matching parameters type
                        if (!(token is TokenWord)) break;
                        var lwToken = token.Value.ToLower();
                        switch (lwToken) {
                            case "buffer":
                                paramPrimitiveType = lwToken;
                                state = 10;
                                break;
                            case "table":
                            case "table-handle":
                            case "dataset":
                            case "dataset-handle":
                                paramPrimitiveType = lwToken;
                                state = 20;
                                break;
                            case "return":
                            case "input":
                            case "output":
                            case "input-output":
                                // flags found before the type in case of a define parameter
                                strFlags = lwToken;
                                break;
                            default:
                                paramName = token.Value;
                                state = 2;
                                break;
                        }
                        break;
                    case 2:
                        // matching parameters as or like
                        if (!(token is TokenWord)) break;
                        var lowerToken = token.Value.ToLower();
                        if (lowerToken.Equals("as")) paramAsLike = ParsedAsLike.As;
                        else if (lowerToken.Equals("like")) paramAsLike = ParsedAsLike.Like;
                        if (paramAsLike != ParsedAsLike.None) state++;
                        break;
                    case 3:
                        // matching parameters primitive type or a field in db
                        if (!(token is TokenWord)) break;
                        paramPrimitiveType = token.Value;
                        state = 99;
                        break;

                    case 10:
                        // match a buffer name
                        if (!(token is TokenWord)) break;
                        paramName = token.Value;
                        state++;
                        break;
                    case 11:
                        // match the table/dataset name that the buffer is FOR
                        if (!(token is TokenWord)) break;
                        lowerToken = token.Value.ToLower();
                        if (token.Value.EqualsCi("for")) break;
                        parameterFor = lowerToken;
                        state = 99;
                        break;

                    case 20:
                        // match a table/dataset name
                        if (!(token is TokenWord)) break;
                        paramName = token.Value;
                        state = 99;
                        break;

                    case 99:
                        // matching parameters "," that indicates a next param
                        if (token is TokenWord && token.Value.EqualsCi("extent")) isExtended = true;
                        else if (token is TokenSymbol && (token.Value.Equals(")") || token.Value.Equals(","))) {
                            // create a variable for this function scope
                            if (!String.IsNullOrEmpty(paramName))
                                parametersList.Add(new ParsedDefine(paramName, functionToken, strFlags, paramAsLike, "", ParseDefineType.Parameter, paramPrimitiveType, "", parameterFor, isExtended, false));
                            paramName = "";
                            paramAsLike = ParsedAsLike.None;
                            paramPrimitiveType = "";
                            strFlags = "";
                            parameterFor = "";
                            isExtended = false;

                            if (token.Value.Equals(","))
                                state = 0;
                            else
                                return parametersList;
                        }
                        break;
                }
                AddTokenToStringBuilder(parameters, token);
            } while (MoveNext());
            return parametersList;
        }
示例#5
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// called when a Eos token is found, store information on the statement's line
        /// </summary>
        private void NewStatement(Token token)
        {
            var statementStartLine = _context.StatementFirstToken != null ? _context.StatementFirstToken.Line : 0;

            // remember the blockDepth of the current token's line (add block depth if the statement started after else of then)
            var depth = GetCurrentDepth();
            if (!_lineInfo.ContainsKey(statementStartLine))
                _lineInfo.Add(statementStartLine, new LineInfo(depth, _context.Scope));

            // add missing values to the line dictionnary
            if (statementStartLine > -1 && token.Line > statementStartLine) {
                for (int i = statementStartLine + 1; i <= token.Line; i++)
                    if (!_lineInfo.ContainsKey(i))
                        _lineInfo.Add(i, new LineInfo(depth + 1, _context.Scope));
            }

            // Pop all the then/else blocks that are on top
            if (_context.BlockStack.Count > 0 && _context.BlockStack.Peek().StatementNumber != _context.StatementCount)
                while (_context.BlockStack.Peek().IndentType == IndentType.ThenElse) {
                    _context.BlockStack.Pop();
                    if (_context.BlockStack.Count == 0)
                        break;
                }

            // This statement made the BlockState count go to 0
            if (_context.BlockStack.Count == 0) {
                // did we match an end of a proc, func or on event block?
                if (!(_context.Scope is ParsedFile)) {
                    var parsedScope = (ParsedScopeItem) _parsedItemList.FindLast(item => item is ParsedScopeItem && !(item is ParsedPreProcBlock));
                    if (parsedScope != null) {
                        parsedScope.EndBlockLine = token.Line;
                        parsedScope.EndBlockPosition = token.EndPosition;
                    }
                    _context.Scope = _rootScope;
                }
            }

            _context.StatementUnknownFirstWord = false;
            _context.StatementCount++;
            _context.StatementWordCount = 0;
            _context.StatementFirstToken = null;
        }
示例#6
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// Creates parsed item for ON CHOOSE OF XXX events
        /// (choose or anything else)
        /// </summary>
        /// <param name="onToken"></param>
        /// <returns></returns>
        private void CreateParsedOnEvent(Token onToken)
        {
            // info we will extract from the current statement :
            var widgetList = new StringBuilder();
            var eventList = new StringBuilder();
            int state = 0;
            do {
                var token = PeekAt(1); // next token
                if (token is TokenEos) break;
                if (token is TokenComment) continue;
                switch (state) {
                    case 0:
                        // matching event type
                        if (!(token is TokenWord) && !(token is TokenString)) break;
                        eventList.Append((eventList.Length == 0 ? "" : ", ") + GetTokenStrippedValue(token));
                        state++;
                        break;
                    case 1:
                        // matching "of"
                        if (token is TokenSymbol && token.Value.Equals(",")) {
                            state--;
                            break;
                        }
                        if (!(token is TokenWord)) break;
                        if (token.Value.EqualsCi("anywhere")) {
                            // we match anywhere, need to return to match a block start
                            widgetList.Append("anywhere");
                            var new1 = new ParsedOnStatement(eventList + " " + widgetList, onToken, eventList.ToString(), widgetList.ToString());
                            AddParsedItem(new1);
                            _context.Scope = new1;
                            return;
                        }
                        // if not anywhere, we expect an "of"
                        if (token.Value.EqualsCi("of")) {
                            state++;
                            break;
                        }
                        // otherwise, return
                        return;
                    case 2:
                        // matching widget name
                        if (token is TokenWord || token is TokenInclude || token is TokenString) {
                            widgetList.Append((widgetList.Length == 0 ? "" : ", ") + GetTokenStrippedValue(token));

                            // we can match several widget name separated by a comma or resume to next state
                            var nextNonSpace = PeekAtNextNonSpace(1);
                            if (!(nextNonSpace is TokenSymbol && nextNonSpace.Value.Equals(",")))
                                state++;
                        }
                        break;
                    case 3:
                        // matching "or", create another parsed item, otherwise leave to match a block start
                        if (!(token is TokenWord)) break;
                        var new2 = new ParsedOnStatement(eventList + " " + widgetList, onToken, eventList.ToString(), widgetList.ToString());
                        AddParsedItem(new2);
                        _context.Scope = new2;
                        if (token.Value.EqualsCi("or")) {
                            state = 0;
                            widgetList.Clear();
                            eventList.Clear();
                        } else
                            return;
                        break;
                }
            } while (MoveNext());
        }
示例#7
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// Matches a procedure definition
        /// </summary>
        /// <param name="procToken"></param>
        private bool CreateParsedProcedure(Token procToken)
        {
            // info we will extract from the current statement :
            string name = "";
            bool isExternal = false;
            bool isPrivate = false;
            _lastTokenWasSpace = true;
            StringBuilder leftStr = new StringBuilder();

            Token token;
            int state = 0;
            do {
                token = PeekAt(1); // next token
                if (token is TokenEos) break;
                if (token is TokenComment) continue;
                switch (state) {
                    case 0:
                        // matching name
                        if (!(token is TokenWord)) continue;
                        name = token.Value;
                        state++;
                        continue;
                    case 1:
                        // matching external
                        if (!(token is TokenWord)) continue;
                        if (token.Value.EqualsCi("external")) isExternal = true;
                        if (token.Value.EqualsCi("private")) isPrivate = true;
                        break;
                }
                AddTokenToStringBuilder(leftStr, token);
            } while (MoveNext());

            if (state < 1) return false;
            var newProc = new ParsedProcedure(name, procToken, leftStr.ToString(), isExternal, isPrivate) {
                // = end position of the EOS of the statement
                EndPosition = token.EndPosition
            };
            AddParsedItem(newProc);
            _context.Scope = newProc;
            return true;
        }
示例#8
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedFunctionCall(string name, Token token, bool externalCall)
     : base(name, token)
 {
     ExternalCall = externalCall;
 }
示例#9
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedImplementation(string name, Token token, string parsedReturnType)
     : base(name, token, parsedReturnType)
 {
     Extend = String.Empty;
 }
示例#10
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedFoundTableUse(string name, Token token, bool isTempTable)
     : base(name, token)
 {
     IsTempTable = isTempTable;
 }
示例#11
0
文件: ParsedItem.cs 项目: jcaillon/3P
 protected ParsedFunction(string name, Token token, string parsedReturnType)
     : base(name, token, ParsedScopeType.Function)
 {
     ParsedReturnType = parsedReturnType;
     Extend = String.Empty;
 }
示例#12
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedFile(string name, Token token)
     : base(name, token, ParsedScopeType.File)
 {
 }
示例#13
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedDefine(string name, Token token, string lcFlagString, ParsedAsLike asLike, string left, ParseDefineType type, string tempPrimitiveType, string viewAs, string bufferFor, bool isExtended, bool isDynamic)
     : base(name, token)
 {
     LcFlagString = lcFlagString;
     AsLike = asLike;
     Left = left;
     Type = type;
     TempPrimitiveType = tempPrimitiveType;
     ViewAs = viewAs;
     BufferFor = bufferFor;
     IsExtended = isExtended;
     IsDynamic = isDynamic;
 }
示例#14
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedTable(string name, Token token, string id, string crc, string dumpName, string description, string lcLikeTable, bool isTempTable, List<ParsedField> fields, List<ParsedIndex> indexes, List<ParsedTrigger> triggers, string lcFlagString, string useIndex)
     : base(name, token)
 {
     Id = id;
     Crc = crc;
     DumpName = dumpName;
     Description = description;
     LcLikeTable = lcLikeTable;
     IsTempTable = isTempTable;
     Fields = fields;
     Indexes = indexes;
     Triggers = triggers;
     LcFlagString = lcFlagString;
     UseIndex = useIndex;
 }
示例#15
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// Matches a & IF.. & THEN pre-processed statement
        /// </summary>
        private ParsedPreProcBlock CreateParsedIfEndIfPreProc(Token ifToken)
        {
            _lastTokenWasSpace = true;
            StringBuilder expression = new StringBuilder();

            do {
                var token = PeekAt(1);
                if (token is TokenEos) break;
                if (token is TokenComment) continue;
                 AddTokenToStringBuilder(expression, token);
            } while (MoveNext());

            var newIf = new ParsedPreProcBlock(string.Empty, ifToken) {
                Type = ParsedPreProcBlockType.IfEndIf,
                BlockDescription = expression.ToString(),
            };
            AddParsedItem(newIf);
            return newIf;
        }
示例#16
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedIncludeFile(string name, Token token)
     : base(name, token)
 {
 }
示例#17
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// matches a include file
        /// </summary>
        /// <param name="token"></param>
        private void CreateParsedIncludeFile(Token token)
        {
            var toParse = token.Value;

            // skip whitespaces
            int startPos = 1;
            while (startPos < toParse.Length) {
                if (!Char.IsWhiteSpace(toParse[startPos])) break;
                startPos++;
            }
            if (toParse[startPos] == '&') return;

            // read first word as the filename
            int curPos = startPos;
            while (curPos < toParse.Length) {
                if (Char.IsWhiteSpace(toParse[curPos]) || toParse[curPos] == '}') break;
                curPos++;
            }
            toParse = toParse.Substring(startPos, curPos - startPos);

            if (!toParse.ContainsFast("."))
                return;

            // we matched the include file name
            AddParsedItem(new ParsedIncludeFile(toParse, token));
        }
示例#18
0
文件: ParsedItem.cs 项目: jcaillon/3P
 protected ParsedItem(string name, Token token)
 {
     Name = name;
     Line = token.Line;
     Column = token.Column;
     Position = token.StartPosition;
     EndPosition = token.EndPosition;
     IncludeLine = -1;
 }
示例#19
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// Analyze a preprocessed statement
        /// </summary>
        /// <param name="token"></param>
        private void CreateParsedPreProc(Token token)
        {
            var toParse = token.Value;
            int pos;
            for (pos = 1; pos < toParse.Length; pos++)
                if (Char.IsWhiteSpace(toParse[pos])) break;

            // extract first word
            var firstWord = toParse.Substring(0, pos);
            int pos2;
            for (pos2 = pos; pos2 < toParse.Length; pos2++)
                if (!Char.IsWhiteSpace(toParse[pos2])) break;
            for (pos = pos2; pos < toParse.Length; pos++)
                if (Char.IsWhiteSpace(toParse[pos])) break;

            // extract define name
            var name = toParse.Substring(pos2, pos - pos2);

            // match first word of the statement
            switch (firstWord.ToUpper()) {
                case "&GLOBAL-DEFINE":
                case "&GLOBAL":
                case "&GLOB":
                    AddParsedItem(new ParsedPreProc(name, token, 0, ParsedPreProcType.Global, toParse.Substring(pos, toParse.Length - pos)));
                    break;

                case "&SCOPED-DEFINE":
                case "&SCOPED":
                    AddParsedItem(new ParsedPreProc(name, token, 0, ParsedPreProcType.Scope, toParse.Substring(pos, toParse.Length - pos)));
                    break;

                case "&ANALYZE-SUSPEND":
                    // it marks the beggining of an appbuilder block, it can only be at a root/File level, otherwise flag error
                    if (!(_context.Scope is ParsedFile)) {
                        _parserErrors.Add(new ParserError(ParserErrorType.NotAllowedUibBlockStart, token, 0));
                        _context.Scope = _rootScope;
                    }

                    // we match a new block start but we didn't match the previous block end, flag error
                    if (_context.UibBlockStack.Count > 0) {
                        _parserErrors.Add(new ParserError(ParserErrorType.UnexpectedUibBlockStart, token, _context.UibBlockStack.Count));
                        _context.UibBlockStack.Clear();
                    }

                    // matching different intersting blocks
                    ParsedPreProcBlockType type = ParsedPreProcBlockType.Unknown;
                    string blockName = "Appbuilder block";
                    if (toParse.ContainsFast("_FUNCTION-FORWARD")) {
                        type = ParsedPreProcBlockType.FunctionForward;
                        blockName = "Function prototype";
                    } else if (toParse.ContainsFast("_MAIN-BLOCK")) {
                        type = ParsedPreProcBlockType.MainBlock;
                        blockName = "Main block";
                    } else if (toParse.ContainsFast("_DEFINITIONS")) {
                        type = ParsedPreProcBlockType.Definitions;
                        blockName = "Definitions";
                    } else if (toParse.ContainsFast("_UIB-PREPROCESSOR-BLOCK")) {
                        type = ParsedPreProcBlockType.UibPreprocessorBlock;
                        blockName = "Pre-processor definitions";
                    } else if (toParse.ContainsFast("_XFTR")) {
                        type = ParsedPreProcBlockType.Xftr;
                        blockName = "Xtfr";
                    } else if (toParse.ContainsFast("_PROCEDURE-SETTINGS")) {
                        type = ParsedPreProcBlockType.ProcedureSettings;
                        blockName = "Procedure settings";
                    } else if (toParse.ContainsFast("_CREATE-WINDOW")) {
                        type = ParsedPreProcBlockType.CreateWindow;
                        blockName = "Window settings";
                    } else if (toParse.ContainsFast("_RUN-TIME-ATTRIBUTES")) {
                        type = ParsedPreProcBlockType.RunTimeAttributes;
                        blockName = "Runtime attributes";
                    }
                    _context.UibBlockStack.Push(new ParsedPreProcBlock(blockName, token) {
                        Type = type,
                        BlockDescription = toParse.Substring(pos2, toParse.Length - pos2),
                    });

                    // save the block description
                    AddParsedItem(_context.UibBlockStack.Peek());
                    break;

                case "&ANALYZE-RESUME":
                    // it marks the end of an appbuilder block, it can only be at a root/File level
                    if (!(_context.Scope is ParsedFile)) {
                        _parserErrors.Add(new ParserError(ParserErrorType.NotAllowedUibBlockEnd, token, 0));
                        _context.Scope = _rootScope;
                    }

                    if (_context.UibBlockStack.Count == 0) {
                        // we match an end w/o beggining, flag a mismatch
                        _parserErrors.Add(new ParserError(ParserErrorType.UnexpectedUibBlockEnd, token, 0));
                    } else {
                        // end position of the current appbuilder block
                        var currentBlock = _context.UibBlockStack.Pop();
                        currentBlock.EndBlockLine = token.Line;
                        currentBlock.EndBlockPosition = token.EndPosition;
                    }

                    break;

                case "&UNDEFINE":
                    var found = (ParsedPreProc) _parsedItemList.FindLast(item => (item is ParsedPreProc && item.Name.Equals(name)));
                    if (found != null)
                        found.UndefinedLine = _context.StatementFirstToken.Line;
                    break;
            }
        }
示例#20
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedLabel(string name, Token token)
     : base(name, token)
 {
 }
示例#21
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// Creates a parsed item for RUN statements
        /// </summary>
        /// <param name="runToken"></param>
        private void CreateParsedRun(Token runToken)
        {
            // info we will extract from the current statement :
            string name = "";
            bool isValue = false;
            bool hasPersistent = false;
            _lastTokenWasSpace = true;
            StringBuilder leftStr = new StringBuilder();
            int state = 0;
            do {
                var token = PeekAt(1); // next token
                if (state == 2) break; // stop after finding the RUN name to be able to match other words in the statement
                if (token is TokenEos) break;
                if (token is TokenComment) continue;
                switch (state) {
                    case 0:
                        // matching proc name (or VALUE)
                        if (token is TokenSymbol && token.Value.Equals(")")) {
                            state++;
                        } else if (isValue && !(token is TokenWhiteSpace || token is TokenSymbol)) {
                            name += GetTokenStrippedValue(token);
                        } else if (token is TokenWord) {
                            if (token.Value.ToLower().Equals("value"))
                                isValue = true;
                            else {
                                name += token.Value;
                                state++;
                            }
                        }
                        break;
                    case 1:
                        // matching PERSISTENT (or a path instead of a file)
                        if (token is TokenSymbol && (token.Value.Equals("/") || token.Value.Equals("\\"))) {
                            // if it's a path, append it to the name of the run
                            name += token.Value;
                            state = 0;
                            break;
                        }
                        if (!(token is TokenWord))
                            break;
                        if (token.Value.EqualsCi("persistent"))
                            hasPersistent = true;
                        state++;
                        break;
                }
            } while (MoveNext());

            if (state == 0) return;
            AddParsedItem(new ParsedRun(name, runToken, leftStr.ToString(), isValue, hasPersistent));
        }
示例#22
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedOnStatement(string name, Token token, string eventList, string widgetList)
     : base(name, token, ParsedScopeType.OnStatement)
 {
     EventList = eventList;
     WidgetList = widgetList;
 }
示例#23
0
文件: Parser.cs 项目: jcaillon/3P
 /// <summary>
 /// Returns token value or token value minus starting/ending quote of the token is a string
 /// </summary>
 /// <param name="token"></param>
 /// <returns></returns>
 private string GetTokenStrippedValue(Token token)
 {
     return (token is TokenString) ? token.Value.Substring(1, token.Value.Length - 2) : token.Value;
 }
示例#24
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedPreProc(string name, Token token, int undefinedLine, ParsedPreProcType type, string value)
     : base(name, token)
 {
     UndefinedLine = undefinedLine;
     Type = type;
     Value = value;
 }
示例#25
0
文件: Parser.cs 项目: jcaillon/3P
 public ParserError(ParserErrorType type, Token triggerToken, int stackCount)
 {
     Type = type;
     TriggerLine = triggerToken.Line;
     TriggerPosition = triggerToken.StartPosition;
     StackCount = stackCount;
 }
示例#26
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedPreProcBlock(string name, Token token)
     : base(name, token, ParsedScopeType.Block)
 {
 }
示例#27
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// Matches a new definition
        /// </summary>
        private void CreateParsedDefine(Token functionToken, bool isDynamic)
        {
            // info we will extract from the current statement :
            string name = "";
            ParsedAsLike asLike = ParsedAsLike.None;
            ParseDefineType type = ParseDefineType.None;
            string tempPrimitiveType = "";
            string viewAs = "";
            string bufferFor = "";
            bool isExtended = false;
            _lastTokenWasSpace = true;
            StringBuilder left = new StringBuilder();
            StringBuilder strFlags = new StringBuilder();

            // for temp tables:
            string likeTable = "";
            bool isTempTable = false;
            var fields = new List<ParsedField>();
            ParsedField currentField = new ParsedField("", "", "", 0, ParsedFieldFlag.None, "", "", ParsedAsLike.None);
            StringBuilder useIndex = new StringBuilder();
            bool isPrimary = false;

            Token token;
            int state = 0;
            do {
                token = PeekAt(1); // next token
                if (token is TokenEos) break;
                if (token is TokenComment) continue;
                string lowerToken;
                bool matchedLikeTable = false;
                switch (state) {

                    case 0:
                        // matching until type of define is found
                        if (!(token is TokenWord)) break;
                        lowerToken = token.Value.ToLower();
                        switch (lowerToken) {
                            case "buffer":
                            case "browse":
                            case "stream":
                            case "button":
                            case "dataset":
                            case "frame":
                            case "query":
                            case "event":
                            case "image":
                            case "menu":
                            case "rectangle":
                            case "property":
                            case "sub-menu":
                            case "parameter":
                                var token1 = lowerToken;
                                foreach (var typ in Enum.GetNames(typeof (ParseDefineType)).Where(typ => token1.Equals(typ.ToLower()))) {
                                    type = (ParseDefineType) Enum.Parse(typeof (ParseDefineType), typ, true);
                                    break;
                                }
                                state++;
                                break;
                            case "data-source":
                                type = ParseDefineType.DataSource;
                                state++;
                                break;
                            case "var":
                            case "variable":
                                type = ParseDefineType.Variable;
                                state++;
                                break;
                            case "temp-table":
                            case "work-table":
                            case "workfile":
                                isTempTable = true;
                                state++;
                                break;
                            case "new":
                            case "global":
                            case "shared":
                            case "private":
                            case "protected":
                            case "public":
                            case "static":
                            case "abstract":
                            case "override":
                                // flags found before the type
                                if (strFlags.Length > 0)
                                    strFlags.Append(" ");
                                strFlags.Append(lowerToken);
                                break;
                            case "input":
                            case "output":
                            case "input-output":
                            case "return":
                                // flags found before the type in case of a define parameter
                                strFlags.Append(lowerToken);
                                break;
                        }
                        break;

                    case 1:
                        // matching the name
                        if (!(token is TokenWord)) break;
                        name = token.Value;
                        if (type == ParseDefineType.Variable) state = 10;
                        if (type == ParseDefineType.Buffer) {
                            tempPrimitiveType = "buffer";
                            state = 31;
                        }
                        if (type == ParseDefineType.Parameter) {
                            lowerToken = token.Value.ToLower();
                            switch (lowerToken) {
                                case "buffer":
                                case "table":
                                case "table-handle":
                                case "dataset":
                                case "dataset-handle":
                                    tempPrimitiveType = lowerToken;
                                    state = 30;
                                    break;
                                default:
                                    state = 10;
                                    break;
                            }
                        }
                        if (isTempTable) state = 20;
                        if (state != 1) break;
                        state = 99;
                        break;

                    case 10:
                        // define variable : match as or like
                        if (!(token is TokenWord)) break;
                        lowerToken = token.Value.ToLower();
                        if (lowerToken.Equals("as")) asLike = ParsedAsLike.As;
                        else if (lowerToken.Equals("like")) asLike = ParsedAsLike.Like;
                        if (asLike != ParsedAsLike.None) state = 11;
                        break;
                    case 11:
                        // define variable : match a primitive type or a field in db
                        if (!(token is TokenWord)) break;
                        tempPrimitiveType = token.Value;
                        state = 12;
                        break;
                    case 12:
                        // define variable : match a view-as (or extent)
                        AddTokenToStringBuilder(left, token);
                        if (!(token is TokenWord)) break;
                        lowerToken = token.Value.ToLower();
                        if (lowerToken.Equals("view-as")) state = 13;
                        if (lowerToken.Equals("extent")) isExtended = true;
                        break;
                    case 13:
                        // define variable : match a view-as
                        AddTokenToStringBuilder(left, token);
                        if (!(token is TokenWord)) break;
                        viewAs = token.Value;
                        state = 99;
                        break;

                    case 20:
                        // define temp-table
                        if (!(token is TokenWord)) break;
                        lowerToken = token.Value.ToLower();
                        switch (lowerToken) {
                            case "field":
                                // matches FIELD
                                state = 22;
                                break;
                            case "index":
                                // matches INDEX
                                state = 25;
                                break;
                            case "use-index":
                                // matches USE-INDEX (after a like/like-sequential, we can have this keyword)
                                state = 26;
                                break;
                            case "help":
                                // a field has a help text:
                                state = 27;
                                break;
                            case "extent":
                                // a field is extent:
                                currentField.Flag = currentField.Flag | ParsedFieldFlag.Extent;
                                break;
                            default:
                                // matches a LIKE table
                                // ReSharper disable once ConditionIsAlwaysTrueOrFalse, resharper doesn't get this one
                                if ((lowerToken.Equals("like") || lowerToken.Equals("like-sequential")) && !matchedLikeTable)
                                    state = 21;
                                // After a USE-UNDEX and the index name, we can match a AS PRIMARY for the previously defined index
                                if (lowerToken.Equals("primary") && useIndex.Length > 0)
                                    useIndex.Append("!");
                                break;
                        }
                        break;
                    case 21:
                        // define temp-table : match a LIKE table, get the table name in asLike
                        // ReSharper disable once RedundantAssignment
                        matchedLikeTable = true;
                        if (!(token is TokenWord)) break;
                        likeTable = token.Value.ToLower();
                        state = 20;
                        break;

                    case 22:
                        // define temp-table : matches a FIELD name
                        if (!(token is TokenWord)) break;
                        currentField = new ParsedField(token.Value, "", "", 0, ParsedFieldFlag.None, "", "", ParsedAsLike.None);
                        state = 23;
                        break;
                    case 23:
                        // define temp-table : matches a FIELD AS or LIKE
                        if (!(token is TokenWord)) break;
                        currentField.AsLike = token.Value.EqualsCi("like") ? ParsedAsLike.Like : ParsedAsLike.As;
                        state = 24;
                        break;
                    case 24:
                        // define temp-table : match a primitive type or a field in db
                        if (!(token is TokenWord)) break;
                        currentField.TempType = token.Value;
                        // push the field to the fields list
                        fields.Add(currentField);
                        state = 20;
                        break;

                    case 25:
                        // define temp-table : match an index definition
                        if (!(token is TokenWord)) break;
                        lowerToken = token.Value.ToLower();
                        if (lowerToken.Equals("primary")) {
                            // ReSharper disable once RedundantAssignment
                            isPrimary = true;
                            break;
                        }
                        var found = fields.Find(field => field.Name.EqualsCi(lowerToken));
                        if (found != null)
                            found.Flag = isPrimary ? ParsedFieldFlag.Primary : ParsedFieldFlag.None;
                        if (lowerToken.Equals("index"))
                            // ReSharper disable once RedundantAssignment
                            isPrimary = false;
                        break;

                    case 26:
                        // define temp-table : match a USE-INDEX name
                        if (!(token is TokenWord)) break;
                        useIndex.Append(",");
                        useIndex.Append(token.Value);
                        state = 20;
                        break;

                    case 27:
                        // define temp-table : match HELP for a field
                        if (!(token is TokenString)) break;
                        currentField.Description = GetTokenStrippedValue(token);
                        state = 20;
                        break;

                    case 30:
                        // define parameter : match a temptable, table, dataset or buffer name
                        if (!(token is TokenWord)) break;
                        if (token.Value.ToLower().Equals("for")) break;
                        name = token.Value;
                        state++;
                        break;
                    case 31:
                        // match the table/dataset name that the buffer or handle is FOR
                        if (!(token is TokenWord)) break;
                        lowerToken = token.Value.ToLower();
                        if (lowerToken.Equals("for") || lowerToken.Equals("temp-table")) break;
                        bufferFor = lowerToken;
                        state = 99;
                        break;

                    case 99:
                        // matching the rest of the define
                        AddTokenToStringBuilder(left, token);
                        break;
                }
            } while (MoveNext());

            if (state <= 1) return;
            if (isTempTable)
                AddParsedItem(new ParsedTable(name, functionToken, "", "", name, "", likeTable, true, fields, new List<ParsedIndex>(), new List<ParsedTrigger>(), strFlags.ToString(), useIndex.ToString()) {
                    // = end position of the EOS of the statement
                    EndPosition = token.EndPosition
                });
            else
                AddParsedItem(new ParsedDefine(name, functionToken, strFlags.ToString(), asLike, left.ToString(), type, tempPrimitiveType, viewAs, bufferFor, isExtended, isDynamic) {
                    // = end position of the EOS of the statement
                    EndPosition = token.EndPosition
                });
        }
示例#28
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedProcedure(string name, Token token, string left, bool isExternal, bool isPrivate)
     : base(name, token, ParsedScopeType.Procedure)
 {
     Left = left;
     IsExternal = isExternal;
     IsPrivate = isPrivate;
 }
示例#29
0
文件: Parser.cs 项目: jcaillon/3P
        /// <summary>
        /// Matches a function definition (not the FORWARD prototype)
        /// </summary>
        private bool CreateParsedFunction(Token functionToken)
        {
            // info we will extract from the current statement :
            string name = null;
            string returnType = null;
            string extend = null;
            bool isExtent = false;
            _lastTokenWasSpace = true;
            StringBuilder parameters = new StringBuilder();
            bool isPrivate = false;
            var parametersList = new List<ParsedItem>();

            Token token;
            int state = 0;
            do {
                token = PeekAt(1); // next token
                if (token is TokenEos) break;
                if (token is TokenComment) continue;
                switch (state) {
                    case 0:
                        // matching name
                        if (!(token is TokenWord)) break;
                        name = token.Value;
                        state++;
                        break;
                    case 1:
                        // matching return type
                        if (!(token is TokenWord)) break;
                        if (token.Value.EqualsCi("returns") || token.Value.EqualsCi("class"))
                            continue;

                        returnType = token.Value;

                        state++;
                        break;
                    case 2:
                        // matching parameters (start)
                        if (token is TokenWord) {
                            if (token.Value.EqualsCi("private"))
                                isPrivate = true;
                            if (token.Value.EqualsCi("extent"))
                                isExtent = true;

                            // we didn't match any opening (, but we found a forward
                            if (token.Value.EqualsCi("forward"))
                                state = 99;
                            else if (token.Value.EqualsCi("in"))
                                state = 100;

                        } else if (token is TokenSymbol && token.Value.Equals("("))
                            state = 3;
                        else if (isExtent && token is TokenNumber)
                            extend = token.Value;
                        break;
                    case 3:
                        // read parameters, define a ParsedDefineItem for each
                        parametersList = GetParsedParameters(functionToken, parameters);
                        state = 10;
                        break;
                    case 10:
                        // matching prototype, we dont want to create a ParsedItem for prototype
                        if (token is TokenWord) {
                            if (token.Value.EqualsCi("forward"))
                                state = 99;
                            else if (token.Value.EqualsCi("in"))
                                state = 100;
                        }
                        break;
                }
            } while (MoveNext());
            if (name == null || returnType == null)
                return false;

            // otherwise it needs to ends with : or .
            if (!(token is TokenEos))
                return false;

            // New prototype, we matched a forward or a IN
            if (state >= 99) {

                ParsedPrototype createdProto = new ParsedPrototype(name, functionToken, returnType) {
                    Scope = _context.Scope,
                    FilePath = _filePathBeingParsed,
                    SimpleForward = state == 99, // allows us to know if we expect an implementation in this .p or not
                    EndPosition = token.EndPosition,
                    EndBlockLine = token.Line,
                    EndBlockPosition = token.EndPosition,
                    IsPrivate = isPrivate,
                    IsExtended = isExtent,
                    Extend = extend ?? string.Empty,
                    Parameters = parameters.ToString()
                };
                if (!_functionPrototype.ContainsKey(name))
                    _functionPrototype.Add(name, createdProto);

                // case of a IN, we add it to the list of item
                if (!createdProto.SimpleForward) {

                    AddParsedItem(createdProto);

                    // modify context
                    _context.Scope = createdProto;

                    // add the parameters to the list
                    if (parametersList.Count > 0) {
                        foreach (var parsedItem in parametersList) {
                            AddParsedItem(parsedItem);
                        }
                    }

                    // reset context
                    _context.Scope = _rootScope;
                }

                return false;

            }

            // New function
            ParsedImplementation createdImp = new ParsedImplementation(name, functionToken, returnType) {
                EndPosition = token.EndPosition,
                IsPrivate = isPrivate,
                IsExtended = isExtent,
                Extend = extend ?? string.Empty,
                Parameters = parameters.ToString()
            };

            // it has a prototype?
            if (_functionPrototype.ContainsKey(name)) {
                // make sure it was a prototype!
                var proto = _functionPrototype[name] as ParsedPrototype;
                if (proto != null && proto.SimpleForward) {

                    createdImp.HasPrototype = true;
                    createdImp.PrototypeLine = proto.Line;
                    createdImp.PrototypeColumn = proto.Column;
                    createdImp.PrototypePosition = proto.Position;
                    createdImp.PrototypeEndPosition = proto.EndPosition;

                    // boolean to know if the implementation matches the prototype
                    createdImp.PrototypeUpdated = (
                        createdImp.IsExtended == proto.IsExtended &&
                        createdImp.IsPrivate == proto.IsPrivate &&
                        createdImp.Extend.Equals(proto.Extend) &&
                        createdImp.ParsedReturnType.Equals(proto.ParsedReturnType) &&
                        createdImp.Parameters.Equals(proto.Parameters));
                }
            } else {
                _functionPrototype.Add(name, createdImp);
            }

            AddParsedItem(createdImp);

            // modify context
            _context.Scope = createdImp;

            // add the parameters to the list
            if (parametersList.Count > 0) {
                foreach (var parsedItem in parametersList) {
                    AddParsedItem(parsedItem);
                }
            }

            return true;
        }
示例#30
0
文件: ParsedItem.cs 项目: jcaillon/3P
 public ParsedRun(string name, Token token, string left, bool isEvaluateValue, bool hasPersistent)
     : base(name, token)
 {
     Left = left;
     IsEvaluateValue = isEvaluateValue;
     HasPersistent = hasPersistent;
 }