protected ParsedScopeItem(string name, Token token, ParsedScopeType scopeType) : base(name, token) { ScopeType = scopeType; EndBlockPosition = -1; }
/// <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); } }
/// <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))); }
/// <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; }
/// <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; }
/// <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()); }
/// <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; }
public ParsedFunctionCall(string name, Token token, bool externalCall) : base(name, token) { ExternalCall = externalCall; }
public ParsedImplementation(string name, Token token, string parsedReturnType) : base(name, token, parsedReturnType) { Extend = String.Empty; }
public ParsedFoundTableUse(string name, Token token, bool isTempTable) : base(name, token) { IsTempTable = isTempTable; }
protected ParsedFunction(string name, Token token, string parsedReturnType) : base(name, token, ParsedScopeType.Function) { ParsedReturnType = parsedReturnType; Extend = String.Empty; }
public ParsedFile(string name, Token token) : base(name, token, ParsedScopeType.File) { }
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; }
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; }
/// <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; }
public ParsedIncludeFile(string name, Token token) : base(name, token) { }
/// <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)); }
protected ParsedItem(string name, Token token) { Name = name; Line = token.Line; Column = token.Column; Position = token.StartPosition; EndPosition = token.EndPosition; IncludeLine = -1; }
/// <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; } }
public ParsedLabel(string name, Token token) : base(name, token) { }
/// <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)); }
public ParsedOnStatement(string name, Token token, string eventList, string widgetList) : base(name, token, ParsedScopeType.OnStatement) { EventList = eventList; WidgetList = widgetList; }
/// <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; }
public ParsedPreProc(string name, Token token, int undefinedLine, ParsedPreProcType type, string value) : base(name, token) { UndefinedLine = undefinedLine; Type = type; Value = value; }
public ParserError(ParserErrorType type, Token triggerToken, int stackCount) { Type = type; TriggerLine = triggerToken.Line; TriggerPosition = triggerToken.StartPosition; StackCount = stackCount; }
public ParsedPreProcBlock(string name, Token token) : base(name, token, ParsedScopeType.Block) { }
/// <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 }); }
public ParsedProcedure(string name, Token token, string left, bool isExternal, bool isPrivate) : base(name, token, ParsedScopeType.Procedure) { Left = left; IsExternal = isExternal; IsPrivate = isPrivate; }
/// <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; }
public ParsedRun(string name, Token token, string left, bool isEvaluateValue, bool hasPersistent) : base(name, token) { Left = left; IsEvaluateValue = isEvaluateValue; HasPersistent = hasPersistent; }