private void CreateSharingMode(CodeElementsParser.CallInputParameterContext parameter,
                                ref SyntaxProperty <ParameterSharingMode> mode)
 {
     if (parameter.REFERENCE() != null)
     {
         mode = CobolStatementsBuilder.CreateSyntaxProperty(ParameterSharingMode.ByReference,
                                                            parameter.REFERENCE());
     }
     else if (parameter.CONTENT() != null)
     {
         mode = CobolStatementsBuilder.CreateSyntaxProperty(ParameterSharingMode.ByContent, parameter.CONTENT());
     }
     else if (parameter.VALUE() != null)
     {
         mode = CobolStatementsBuilder.CreateSyntaxProperty(ParameterSharingMode.ByValue, parameter.VALUE());
     }
     else
     {
         var by = ParameterSharingMode.ByReference;
         if (mode != null)
         {
             by = mode.Value;
         }
         mode = new SyntaxProperty <ParameterSharingMode>(by, null);
     }
 }
Beispiel #2
0
 private static StringBuilder Dump <T>(StringBuilder str, SyntaxProperty <T> data)
 {
     if (data == null)
     {
         str.Append("?");
     }
     else
     {
         str.Append(data.Value);
     }
     return(str);
 }
Beispiel #3
0
 public LogicalOperation(ConditionalExpression leftOperand, SyntaxProperty<LogicalOperator> logicalOperator, ConditionalExpression rightOperand)
     : base(ExpressionNodeType.LogicalOperation)
 {
     LeftOperand = leftOperand;
     Operator = logicalOperator;
     RightOperand = rightOperand;
 }
Beispiel #4
0
 public ClassCondition(StorageArea dataItem, SyntaxProperty<DataItemContentType> dataItemContentType, SyntaxProperty<bool> invertResult)
     : base(ExpressionNodeType.ClassCondition)
 {
     DataItem = dataItem;
     DataItemContentType = dataItemContentType;
     InvertResult = invertResult;
 }
Beispiel #5
0
 public ClassCondition(StorageArea dataItem, SymbolReference characterClassNameReference, SyntaxProperty<bool> invertResult)
     : base(ExpressionNodeType.ClassCondition)
 {
     DataItem = dataItem;
     CharacterClassNameReference = characterClassNameReference;
     InvertResult = invertResult;
 }
Beispiel #6
0
 public ArithmeticOperation(ArithmeticExpression left, SyntaxProperty<ArithmeticOperator> op, ArithmeticExpression right = null)
     : base(ExpressionNodeType.ArithmeticOperation)
 {
     LeftOperand = left;
     Operator = op;
     RightOperand = right;
 }
 private void CreateSharingMode(CodeElementsParser.CallInputParameterContext parameter, ref SyntaxProperty<ParameterSharingMode> mode)
 {
     if (parameter.REFERENCE() != null) {
     mode = CobolStatementsBuilder.CreateSyntaxProperty(ParameterSharingMode.ByReference, parameter.REFERENCE());
     } else
     if (parameter.CONTENT()   != null) {
     mode = CobolStatementsBuilder.CreateSyntaxProperty(ParameterSharingMode.ByContent,   parameter.CONTENT());
     } else
     if (parameter.VALUE()     != null) {
     mode = CobolStatementsBuilder.CreateSyntaxProperty(ParameterSharingMode.ByValue,     parameter.VALUE());
     } else {
     var by = ParameterSharingMode.ByReference;
     if (mode != null) by = mode.Value;
     mode = new SyntaxProperty<ParameterSharingMode>(by, null);
     }
 }
        public override void EnterDataDescriptionEntry(CodeElementsParser.DataDescriptionEntryContext context)
        {
            if (context.dataRenamesEntry() != null || context.dataConditionEntry() != null) {
                // For levels 66 and 88, the DataDefinitionEntry is created by the following methods
                // - EnterDataRenamesEntry
                // - EnterDataConditionEntry
                return;
            }
            if (context.redefinesClause() != null) {
                // Redefines clause is not a separate rule in the grammar for optimization puroposes,
                // but we pretend here that it is a separate rule
                EnterDataRedefinesEntry(context);
                return;
            }

            DataDescriptionEntry entry;
            // [COBOL 2002]
            if (context.cobol2002TypedefClause() != null) {
                var typedef = new DataTypeDescriptionEntry();
                typedef.DataTypeName = CobolWordsBuilder.CreateDataTypeNameDefinition(context.dataNameDefinition());
                var strong = context.cobol2002TypedefClause().STRONG();
                typedef.Strong = new SyntaxProperty<bool>(strong != null, ParseTreeUtils.GetFirstToken(strong));

                entry = typedef;
                entry.DataName = typedef.DataTypeName;
                entry.DataType = new DataType(typedef.DataTypeName.Name, typedef.IsStrong);
            }
            // [/COBOL 2002]
            else {
                entry = new DataDescriptionEntry();
                entry.DataName = CobolWordsBuilder.CreateDataNameDefinition(context.dataNameDefinition());
                entry.DataType = DataType.Unknown;
            }

            if (context.levelNumber() != null)
                entry.LevelNumber = CobolWordsBuilder.CreateIntegerValue(context.levelNumber().integerValue());

            if (context.FILLER() != null) entry.Filler = new SyntaxProperty<bool>(true, ParseTreeUtils.GetFirstToken(context.FILLER()));
            else entry.Filler = new SyntaxProperty<bool>(entry.DataName == null, null);

            if (context.pictureClause() != null && context.pictureClause().Length > 0) {
                var pictureClauseContext = context.pictureClause()[0];
                entry.Picture = CobolWordsBuilder.CreateAlphanumericValue(pictureClauseContext.pictureCharacterString);
                if (entry.DataType == DataType.Unknown) // only for a basic TYPEDEF <typename> PIC <picture>
                    entry.DataType = DataType.Create(entry.Picture.Value);
            }
            // [COBOL 2002]
            if (context.cobol2002TypeClause() != null && context.cobol2002TypeClause().Length > 0) {
                entry.UserDefinedDataType = CobolWordsBuilder.CreateDataTypeNameReference(context.cobol2002TypeClause()[0].dataTypeNameReference());
                entry.DataType = DataType.CreateCustom(entry.UserDefinedDataType.Name);
            }
            // [/COBOL 2002]
            if (context.blankWhenZeroClause() != null && context.blankWhenZeroClause().Length > 0)
            {
                var blankClauseContext = context.blankWhenZeroClause()[0];
                Token zeroToken = null;
                if (blankClauseContext.ZERO() != null)
                {
                    zeroToken = ParseTreeUtils.GetFirstToken(blankClauseContext.ZERO());
                }
                else if (blankClauseContext.ZEROS() != null)
                {
                    zeroToken = ParseTreeUtils.GetFirstToken(blankClauseContext.ZEROS());
                }
                else
                {
                    zeroToken = ParseTreeUtils.GetFirstToken(blankClauseContext.ZEROES());
                }
                entry.IsBlankWhenZero = new SyntaxProperty<bool>(true, zeroToken);
            }

            if (context.externalClause() != null && context.externalClause().Length > 0) {
                entry.External = new SyntaxProperty<bool>(true, ParseTreeUtils.GetFirstToken(context.externalClause()[0].EXTERNAL()));
            }
            if (context.globalClause() != null && context.globalClause().Length > 0) {
                entry.Global = new SyntaxProperty<bool>(true, ParseTreeUtils.GetFirstToken(context.globalClause()[0].GLOBAL()));
            }
            if (context.justifiedClause() != null && context.justifiedClause().Length > 0)
            {
                var justifiedClauseContext = context.justifiedClause()[0];
                Token justifiedToken = null;
                if (justifiedClauseContext.JUSTIFIED() != null)
                {
                    justifiedToken = ParseTreeUtils.GetFirstToken(justifiedClauseContext.JUSTIFIED());
                }
                else
                {
                    justifiedToken = ParseTreeUtils.GetFirstToken(justifiedClauseContext.JUST());
                }
                entry.IsJustified = new SyntaxProperty<bool>(true, justifiedToken);
            }
            if (context.groupUsageClause() != null && context.groupUsageClause().Length > 0)
            {
                var groupUsageClauseContext = context.groupUsageClause()[0];
                entry.IsJustified = new SyntaxProperty<bool>(true,
                    ParseTreeUtils.GetFirstToken(groupUsageClauseContext.NATIONAL()));
            }
            if (context.occursClause() != null && context.occursClause().Length > 0)
            {
                var occursClauseContext = context.occursClause()[0];
                if (occursClauseContext.minNumberOfOccurences != null)
                {
                    entry.MinOccurencesCount = CobolWordsBuilder.CreateIntegerValue(occursClauseContext.minNumberOfOccurences);
                }
                if (occursClauseContext.maxNumberOfOccurences != null)
                {
                    entry.MaxOccurencesCount = CobolWordsBuilder.CreateIntegerValue(occursClauseContext.maxNumberOfOccurences);
                }
                if (entry.MinOccurencesCount == null && entry.MaxOccurencesCount != null)
                {
                    entry.MinOccurencesCount = entry.MaxOccurencesCount;
                }
                if (occursClauseContext.UNBOUNDED() != null)
                {
                    entry.HasUnboundedNumberOfOccurences = new SyntaxProperty<bool>(true,
                        ParseTreeUtils.GetFirstToken(occursClauseContext.UNBOUNDED()));
                }
                if (occursClauseContext.varNumberOfOccurences != null)
                {
                    entry.OccursDependingOn = CobolExpressionsBuilder.CreateNumericVariable(occursClauseContext.varNumberOfOccurences);
                }
                if (occursClauseContext.tableSortingKeys() != null && occursClauseContext.tableSortingKeys().Length > 0)
                {
                    int keysCount = 0;
                    foreach (var tableSortingKeysContext in occursClauseContext.tableSortingKeys())
                    {
                        keysCount += tableSortingKeysContext.dataNameReference().Length;
                    }
                    entry.TableSortingKeys = new TableSortingKey[keysCount];
                    int keyIndex = 0;
                    foreach (var tableSortingKeysContext in occursClauseContext.tableSortingKeys())
                    {
                        SyntaxProperty<SortDirection> sortDirection = null;
                        if (tableSortingKeysContext.ASCENDING() != null)
                        {
                            sortDirection = new SyntaxProperty<SortDirection>(SortDirection.Ascending,
                                ParseTreeUtils.GetFirstToken(tableSortingKeysContext.ASCENDING()));
                        }
                        else
                        {
                            sortDirection = new SyntaxProperty<SortDirection>(SortDirection.Descending,
                                ParseTreeUtils.GetFirstToken(tableSortingKeysContext.DESCENDING()));
                        }
                        foreach (var dataNameReference in tableSortingKeysContext.dataNameReference())
                        {
                            SymbolReference sortKey = CobolWordsBuilder.CreateDataNameReference(dataNameReference);
                            entry.TableSortingKeys[keyIndex] = new TableSortingKey(sortKey, sortDirection);
                            keyIndex++;
                        }
                    }
                }
                if (occursClauseContext.indexNameDefinition() != null && occursClauseContext.indexNameDefinition().Length > 0)
                {
                    entry.Indexes = new SymbolDefinition[occursClauseContext.indexNameDefinition().Length];
                    for (int i = 0; i < occursClauseContext.indexNameDefinition().Length; i++)
                    {
                        var indexNameDefinition = occursClauseContext.indexNameDefinition()[i];
                        entry.Indexes[i] = CobolWordsBuilder.CreateIndexNameDefinition(indexNameDefinition);
                    }
                }
            }
            if (context.signClause() != null && context.signClause().Length > 0)
            {
                var signClauseContext = context.signClause()[0];
                if (signClauseContext.LEADING() != null)
                {
                    entry.SignPosition = new SyntaxProperty<SignPosition>(SignPosition.Leading,
                        ParseTreeUtils.GetFirstToken(signClauseContext.LEADING()));
                }
                else
                {
                    entry.SignPosition = new SyntaxProperty<SignPosition>(SignPosition.Trailing,
                        ParseTreeUtils.GetFirstToken(signClauseContext.TRAILING()));
                }
                if (signClauseContext.SEPARATE() != null)
                {
                    entry.SignIsSeparate = new SyntaxProperty<bool>(true,
                        ParseTreeUtils.GetFirstToken(signClauseContext.SEPARATE()));
                }
            }
            if (context.synchronizedClause() != null && context.synchronizedClause().Length > 0)
            {
                var synchronizedClauseContext = context.synchronizedClause()[0];
                if (synchronizedClauseContext.SYNCHRONIZED() != null)
                {
                    entry.IsSynchronized = new SyntaxProperty<bool>(true,
                        ParseTreeUtils.GetFirstToken(synchronizedClauseContext.SYNCHRONIZED()));
                }
                else
                {
                    entry.IsSynchronized = new SyntaxProperty<bool>(true,
                        ParseTreeUtils.GetFirstToken(synchronizedClauseContext.SYNC()));
                }
            }
            if (context.usageClause() != null && context.usageClause().Length > 0) {
                entry.Usage = CreateUsageClause(context.usageClause()[0]);
            }
            if (context.valueClause() != null && context.valueClause().Length > 0)
            {
                var valueClauseContext = context.valueClause()[0];
                entry.InitialValue = CobolWordsBuilder.CreateValue(valueClauseContext.value2());
            }

            Context = context;
            CodeElement = entry;
        }
        internal SubscriptExpression[] CreateSubscriptExpressions(CodeElementsParser.SubscriptContext[] contextArray)
        {
            SubscriptExpression[] subscriptExpressions = new SubscriptExpression[contextArray.Length];
            for(int i = 0; i < contextArray.Length; i++)
            {
                CodeElementsParser.SubscriptContext context = contextArray[i];
                if(context.ALL() != null)
                {
                    subscriptExpressions[i] = new SubscriptExpression(
                        ParseTreeUtils.GetFirstToken(context.ALL()));
                }
                else
                {
                    IntegerVariable integerVariable = CreateIntegerVariableOrIndex(context.integerVariableOrIndex2());
                    ArithmeticExpression arithmeticExpression = new NumericVariableOperand(integerVariable);
                    if(context.withRelativeSubscripting() != null)
                    {
                        SyntaxProperty<ArithmeticOperator> arithmeticOperator = null;
                        if(context.withRelativeSubscripting().PlusOperator() != null)
                        {
                            arithmeticOperator = new SyntaxProperty<ArithmeticOperator>(
                                ArithmeticOperator.Plus,
                                ParseTreeUtils.GetFirstToken(context.withRelativeSubscripting().PlusOperator()));
                        }
                        else
                        {
                            arithmeticOperator = new SyntaxProperty<ArithmeticOperator>(
                                ArithmeticOperator.Minus,
                                ParseTreeUtils.GetFirstToken(context.withRelativeSubscripting().MinusOperator()));
                        }

                        IntegerVariable integerVariable2 = new IntegerVariable(
                            CobolWordsBuilder.CreateIntegerValue(context.withRelativeSubscripting().integerValue()));
                        ArithmeticExpression numericOperand2 = new NumericVariableOperand(integerVariable2);

                        arithmeticExpression = new ArithmeticOperation(
                            arithmeticExpression,
                            arithmeticOperator,
                            numericOperand2);
                    }
                    subscriptExpressions[i] = new SubscriptExpression(arithmeticExpression);
                }
            }
            return subscriptExpressions;
        }
        internal ConditionalExpression CreateSignCondition(CodeElementsParser.SignConditionContext context)
        {
            SyntaxProperty<bool> invertResult = null;
            if (context.NOT() != null)
            {
                invertResult = new SyntaxProperty<bool>(
                    true,
                    ParseTreeUtils.GetFirstToken(context.NOT()));
            }
            SyntaxProperty<SignComparison> signComparison = null;
            if(context.POSITIVE() != null)
            {
                signComparison = new SyntaxProperty<SignComparison>(
                    SignComparison.Positive,
                    ParseTreeUtils.GetFirstToken(context.POSITIVE()));
            }
            else if (context.NEGATIVE() != null)
            {
                signComparison = new SyntaxProperty<SignComparison>(
                    SignComparison.Negative,
                    ParseTreeUtils.GetFirstToken(context.NEGATIVE()));
            }
            else if (context.ZERO() != null)
            {
                signComparison = new SyntaxProperty<SignComparison>(
                    SignComparison.Zero,
                    ParseTreeUtils.GetFirstToken(context.ZERO()));
            }

            return new SignCondition(
                CreateConditionOperand(context.conditionOperand()),
                signComparison,
                invertResult);
        }
        // --- Arithmetic Expressions ---
        internal ArithmeticExpression CreateArithmeticExpression(CodeElementsParser.ArithmeticExpressionContext context)
        {
            if(context.numericVariable3() != null)
            {
                return new NumericVariableOperand(
                    CreateNumericVariable(context.numericVariable3()));
            }

            SyntaxProperty<ArithmeticOperator> arithmeticOperator = null;
            if (context.PlusOperator() != null)
            {
                if (context.arithmeticExpression() != null && context.arithmeticExpression().Length == 1)
                {
                    arithmeticOperator = new SyntaxProperty<ArithmeticOperator>(
                        ArithmeticOperator.UnaryPlus,
                        ParseTreeUtils.GetFirstToken(context.PlusOperator()));
                }
                else
                {
                    arithmeticOperator = new SyntaxProperty<ArithmeticOperator>(
                        ArithmeticOperator.Plus,
                        ParseTreeUtils.GetFirstToken(context.PlusOperator()));
                }
            }
            else if (context.MinusOperator() != null)
            {
                if (context.arithmeticExpression() != null && context.arithmeticExpression().Length == 1)
                {
                    arithmeticOperator = new SyntaxProperty<ArithmeticOperator>(
                        ArithmeticOperator.UnaryMinus,
                        ParseTreeUtils.GetFirstToken(context.MinusOperator()));
                }
                else
                {
                    arithmeticOperator = new SyntaxProperty<ArithmeticOperator>(
                        ArithmeticOperator.Minus,
                        ParseTreeUtils.GetFirstToken(context.MinusOperator()));
                }
            }
            else if (context.PowerOperator() != null)
            {
                arithmeticOperator = new SyntaxProperty<ArithmeticOperator>(
                    ArithmeticOperator.Power,
                    ParseTreeUtils.GetFirstToken(context.PowerOperator()));
            }
            else if (context.MultiplyOperator() != null)
            {
                arithmeticOperator = new SyntaxProperty<ArithmeticOperator>(
                    ArithmeticOperator.Multiply,
                    ParseTreeUtils.GetFirstToken(context.MultiplyOperator()));
            }
            else if (context.DivideOperator() != null)
            {
                arithmeticOperator = new SyntaxProperty<ArithmeticOperator>(
                    ArithmeticOperator.Divide,
                    ParseTreeUtils.GetFirstToken(context.DivideOperator()));
            }

            if (arithmeticOperator == null)
            {
                return CreateArithmeticExpression(context.arithmeticExpression()[0]);
            }
            else
            {
                if (context.arithmeticExpression().Length == 1)
                {
                    ArithmeticExpression rightOperand = CreateArithmeticExpression(context.arithmeticExpression()[0]);
                    return new ArithmeticOperation(null, arithmeticOperator, rightOperand);
                }
                else
                {
                    ArithmeticExpression leftOperand = CreateArithmeticExpression(context.arithmeticExpression()[0]);
                    ArithmeticExpression rightOperand = CreateArithmeticExpression(context.arithmeticExpression()[1]);
                    return new ArithmeticOperation(leftOperand, arithmeticOperator, rightOperand);
                }
            }
        }
        // --- Conditional Expressions ---
        internal ConditionalExpression CreateConditionalExpression(CodeElementsParser.ConditionalExpressionContext context)
        {
            if(context.classCondition() != null)
            {
                return CreateClassCondition(context.classCondition());
            }
            else if(context.conditionNameConditionOrSwitchStatusCondition() != null)
            {
                return CreateConditionNameConditionOrSwitchStatusCondition(context.conditionNameConditionOrSwitchStatusCondition());
            }
            else if(context.relationCondition() != null)
            {
                return CreateRelationCondition(context.relationCondition());
            }
            else if(context.signCondition() != null)
            {
                return CreateSignCondition(context.signCondition());
            }
            else
            {
                SyntaxProperty<LogicalOperator> logicalOperator = null;
                if(context.NOT() != null)
                {
                    logicalOperator = new SyntaxProperty<LogicalOperator>(
                       LogicalOperator.NOT,
                       ParseTreeUtils.GetFirstToken(context.NOT()));
                }
                else if (context.AND() != null)
                {
                    logicalOperator = new SyntaxProperty<LogicalOperator>(
                       LogicalOperator.AND,
                       ParseTreeUtils.GetFirstToken(context.AND()));
                }
                else if (context.OR() != null)
                {
                    logicalOperator = new SyntaxProperty<LogicalOperator>(
                       LogicalOperator.OR,
                       ParseTreeUtils.GetFirstToken(context.OR()));
                }

                if (logicalOperator == null)
                {
                    return CreateConditionalExpression(context.conditionalExpression()[0]);
                }
                else
                {
                    if (context.conditionalExpression().Length == 1)
                    {
                        ConditionalExpression rightOperand = CreateConditionalExpression(context.conditionalExpression()[0]);
                        return new LogicalOperation(null, logicalOperator, rightOperand);
                    }
                    else
                    {
                        ConditionalExpression leftOperand = CreateConditionalExpression(context.conditionalExpression()[0]);
                        ConditionalExpression rightOperand = CreateConditionalExpression(context.conditionalExpression()[1]);
                        return new LogicalOperation(leftOperand, logicalOperator, rightOperand);
                    }
                }
            }
        }
        internal ConditionalExpression CreateClassCondition(CodeElementsParser.ClassConditionContext context)
        {
            SyntaxProperty<bool> invertResult = null;
            if (context.NOT() != null)
            {
                invertResult = new SyntaxProperty<bool>(
                    true,
                    ParseTreeUtils.GetFirstToken(context.NOT()));
            }

            ClassCondition classCondition = null;
            if(context.characterClassNameReference() != null)
            {
                classCondition = new ClassCondition(
                    CreateIdentifier(context.identifier()),
                    CobolWordsBuilder.CreateCharacterClassNameReference(context.characterClassNameReference()),
                    invertResult);
            }
            else
            {
                DataItemContentType contentTypeEnum = DataItemContentType.Numeric;
                if(context.dataItemContentType().ALPHABETIC() != null)
                {
                    contentTypeEnum = DataItemContentType.Alphabetic;
                }
                else if (context.dataItemContentType().ALPHABETIC_LOWER() != null)
                {
                    contentTypeEnum = DataItemContentType.AlphabeticLower;
                }
                else if (context.dataItemContentType().ALPHABETIC_UPPER() != null)
                {
                    contentTypeEnum = DataItemContentType.AlphabeticUpper;
                }
                else if (context.dataItemContentType().DBCS() != null)
                {
                    contentTypeEnum = DataItemContentType.DBCS;
                }
                else if (context.dataItemContentType().KANJI() != null)
                {
                    contentTypeEnum = DataItemContentType.Kanji;
                }
                SyntaxProperty<DataItemContentType> dataItemContentType = new SyntaxProperty<DataItemContentType>(
                    contentTypeEnum,
                    ParseTreeUtils.GetFirstToken(context.dataItemContentType()));

                classCondition = new ClassCondition(
                    CreateIdentifier(context.identifier()),
                    dataItemContentType,
                    invertResult);
            }

            return classCondition;
        }
        private ConditionalExpression CreateAbbreviatedExpression(ConditionOperand subjectOperand, SyntaxProperty<RelationalOperator> distributedRelationalOperator, CodeElementsParser.AbbreviatedExpressionContext context)
        {
            if (context.conditionOperand() != null)
            {
                ConditionOperand objectOperand = CreateConditionOperand(context.conditionOperand());
                SyntaxProperty<RelationalOperator> relationalOperator = distributedRelationalOperator;
                if (context.relationalOperator() != null)
                {
                    relationalOperator = CreateRelationalOperator(context.relationalOperator());
                }
                return new RelationCondition(subjectOperand, relationalOperator, objectOperand);
            }
            else
            {
                SyntaxProperty<LogicalOperator> logicalOperator = null;
                if (context.NOT() != null)
                {
                    logicalOperator = new SyntaxProperty<LogicalOperator>(
                       LogicalOperator.NOT,
                       ParseTreeUtils.GetFirstToken(context.NOT()));
                }
                else if (context.AND() != null)
                {
                    logicalOperator = new SyntaxProperty<LogicalOperator>(
                       LogicalOperator.AND,
                       ParseTreeUtils.GetFirstToken(context.AND()));
                }
                else if (context.OR() != null)
                {
                    logicalOperator = new SyntaxProperty<LogicalOperator>(
                       LogicalOperator.OR,
                       ParseTreeUtils.GetFirstToken(context.OR()));
                }

                if (logicalOperator == null)
                {
                    return CreateAbbreviatedExpression(subjectOperand, distributedRelationalOperator, context.abbreviatedExpression()[0]);
                }
                else
                {
                    if (context.abbreviatedExpression().Length == 1)
                    {
                        ConditionalExpression rightOperand = CreateAbbreviatedExpression(subjectOperand, distributedRelationalOperator, context.abbreviatedExpression()[0]);
                        return new LogicalOperation(null, logicalOperator, rightOperand);
                    }
                    else
                    {
                        ConditionalExpression leftOperand = CreateAbbreviatedExpression(subjectOperand, distributedRelationalOperator, context.abbreviatedExpression()[0]);
                        ConditionalExpression rightOperand = CreateAbbreviatedExpression(subjectOperand, distributedRelationalOperator, context.abbreviatedExpression()[1]);
                        return new LogicalOperation(leftOperand, logicalOperator, rightOperand);
                    }
                }
            }
        }
Beispiel #15
0
 public RelationCondition(ConditionOperand leftOperand, SyntaxProperty<RelationalOperator> relationalOperator, ConditionOperand rightOperand)
     : base(ExpressionNodeType.RelationCondition)
 {
     LeftOperand = leftOperand;
     Operator = relationalOperator;
     RightOperand = rightOperand;
 }
Beispiel #16
0
 public SignCondition(ConditionOperand operand, SyntaxProperty<SignComparison> signComparison, SyntaxProperty<bool> invertResult)
     : base(ExpressionNodeType.SignCondition)
 {
     Operand = operand;
     SignComparison = signComparison;
     InvertResult = invertResult;
 }
Beispiel #17
0
 public SubscriptExpression(Token allToken)
 {
     ALL = new SyntaxProperty<bool>(true, allToken);
 }
        public override void EnterFileControlEntry(CodeElementsParser.FileControlEntryContext context)
        {
            var entry = new FileControlEntry();

            if (context.selectClause() != null)
            {
                entry.FileName = CobolWordsBuilder.CreateFileNameDefinition(context.selectClause().fileNameDefinition());
                if (context.selectClause().OPTIONAL() != null)
                {
                    entry.IsOptional = new SyntaxProperty<bool>(true,
                        ParseTreeUtils.GetFirstToken(context.selectClause().OPTIONAL()));
                }
            }
            if (context.assignClause() != null && context.assignClause().Length > 0)
            {
                var assignClauseContext = context.assignClause()[0];
                entry.ExternalDataSet = CobolWordsBuilder.CreateAssignmentName(assignClauseContext.assignmentName()[0]);
            }
            if (context.reserveClause() != null && context.reserveClause().Length > 0)
            {
                var reserveClauseContext = context.reserveClause()[0];
                entry.ReserveIOBuffersCount = CobolWordsBuilder.CreateIntegerValue(reserveClauseContext.integerValue());
            }
            if (context.accessModeClause() != null && context.accessModeClause().Length > 0)
            {
                var accessModeClauseContext = context.accessModeClause()[0];
                if (accessModeClauseContext.SEQUENTIAL() != null)
                {
                    entry.AccessMode = new SyntaxProperty<FileAccessMode>(FileAccessMode.Sequential,
                        ParseTreeUtils.GetFirstToken(accessModeClauseContext.SEQUENTIAL()));
                }
                else if (accessModeClauseContext.RANDOM() != null)
                {
                    entry.AccessMode = new SyntaxProperty<FileAccessMode>(FileAccessMode.Random,
                        ParseTreeUtils.GetFirstToken(accessModeClauseContext.RANDOM()));
                }
                else if (accessModeClauseContext.DYNAMIC() != null)
                {
                    entry.AccessMode = new SyntaxProperty<FileAccessMode>(FileAccessMode.Dynamic,
                        ParseTreeUtils.GetFirstToken(accessModeClauseContext.DYNAMIC()));
                }
            }
            if (context.fileStatusClause() != null && context.fileStatusClause().Length > 0)
            {
                var fileStatusClauseContext = context.fileStatusClause()[0];
                entry.FileStatus = CobolExpressionsBuilder.CreateStorageArea(fileStatusClauseContext.fileStatus);
                if (fileStatusClauseContext.vsamReturnCode != null)
                {
                    entry.VSAMReturnCode = CobolExpressionsBuilder.CreateStorageArea(fileStatusClauseContext.vsamReturnCode);
                }
            }

            SyntaxProperty<FileRecordsOrganization> recordsOrganization = null;
            CharacterVariable paddingCharacter = null;
            Token recordDelimiter = null;
            SymbolReference recordKey = null;
            AlternateRecordKey[] alternateRecordKeys = null;
            SymbolReference relativeKey = null;
            SymbolReference password = null;
            if (context.organizationClause() != null && context.organizationClause().Length > 0)
            {
                var organizationClauseContext = context.organizationClause()[0];
                if (organizationClauseContext.SEQUENTIAL() != null)
                {
                    recordsOrganization = new SyntaxProperty<FileRecordsOrganization>(FileRecordsOrganization.Sequential,
                        ParseTreeUtils.GetFirstToken(organizationClauseContext.SEQUENTIAL()));
                }
                else if (organizationClauseContext.INDEXED() != null)
                {
                    recordsOrganization = new SyntaxProperty<FileRecordsOrganization>(FileRecordsOrganization.Indexed,
                        ParseTreeUtils.GetFirstToken(organizationClauseContext.INDEXED()));
                }
                else if (organizationClauseContext.RELATIVE() != null)
                {
                    recordsOrganization = new SyntaxProperty<FileRecordsOrganization>(FileRecordsOrganization.Relative,
                        ParseTreeUtils.GetFirstToken(organizationClauseContext.RELATIVE()));
                }
                if (organizationClauseContext.LINE() != null)
                {
                    recordsOrganization = new SyntaxProperty<FileRecordsOrganization>(FileRecordsOrganization.LineSequential,
                        ParseTreeUtils.GetFirstToken(organizationClauseContext.LINE()));
                }
            }
            if (context.paddingCharacterClause() != null && context.paddingCharacterClause().Length > 0)
            {
                var paddingCharacterClauseContext = context.paddingCharacterClause()[0];
                paddingCharacter = CobolExpressionsBuilder.CreateCharacterVariable(paddingCharacterClauseContext.characterVariable());
            }
            if (context.recordDelimiterClause() != null && context.recordDelimiterClause().Length > 0)
            {
                var recordDelimiterClauseContext = context.recordDelimiterClause()[0];
                if (recordDelimiterClauseContext.STANDARD_1() != null)
                {
                    recordDelimiter = ParseTreeUtils.GetFirstToken(recordDelimiterClauseContext.STANDARD_1());
                }
                else if (recordDelimiterClauseContext.literalOrUserDefinedWordOReservedWordExceptCopy() != null)
                {
                    recordDelimiter = ParseTreeUtils.GetFirstToken(recordDelimiterClauseContext.literalOrUserDefinedWordOReservedWordExceptCopy());
                }
            }
            if (context.recordKeyClause() != null && context.recordKeyClause().Length > 0)
            {
                var recordKeyClauseContext = context.recordKeyClause()[0];
                recordKey = CobolWordsBuilder.CreateDataNameReference(recordKeyClauseContext.dataNameReference());
            }
            if (context.alternateRecordKeyClause() != null && context.alternateRecordKeyClause().Length > 0)
            {
                alternateRecordKeys = new AlternateRecordKey[context.alternateRecordKeyClause().Length];
                for (int i = 0; i < context.alternateRecordKeyClause().Length; i++)
                {
                    var alternateRecordKeyClauseContext = context.alternateRecordKeyClause()[i];
                    alternateRecordKeys[i] = new AlternateRecordKey();
                    alternateRecordKeys[i].RecordKey = CobolWordsBuilder.CreateDataNameReference(alternateRecordKeyClauseContext.recordKey);
                    if (alternateRecordKeyClauseContext.DUPLICATES() != null)
                    {
                        alternateRecordKeys[i].AllowDuplicates = new SyntaxProperty<bool>(true,
                            ParseTreeUtils.GetFirstToken(alternateRecordKeyClauseContext.DUPLICATES()));
                    }
                    if (alternateRecordKeyClauseContext.password != null)
                    {
                        alternateRecordKeys[i].Password = CobolWordsBuilder.CreateDataNameReference(alternateRecordKeyClauseContext.password);
                    }
                }
            }
            if (context.relativeKeyClause() != null && context.relativeKeyClause().Length > 0)
            {
                var relativeKeyClauseContext = context.relativeKeyClause()[0];
                relativeKey = CobolWordsBuilder.CreateDataNameReference(relativeKeyClauseContext.dataNameReference());
            }
            if (context.passwordClause() != null && context.passwordClause().Length > 0)
            {
                var passwordClauseContext = context.passwordClause()[0];
                password = CobolWordsBuilder.CreateDataNameReference(passwordClauseContext.dataNameReference());
            }
            if (recordsOrganization != null)
            {
                switch (recordsOrganization.Value)
                {
                    case FileRecordsOrganization.Sequential:
                    case FileRecordsOrganization.LineSequential:
                        var sequentialFileStructure = new SequentialFileStructure();
                        sequentialFileStructure.RecordsOrganization = recordsOrganization;
                        sequentialFileStructure.PaddingCharacter = paddingCharacter;
                        sequentialFileStructure.RecordDelimiter = recordDelimiter;
                        sequentialFileStructure.Password = password;
                        entry.Structure = sequentialFileStructure;
                        break;
                    case FileRecordsOrganization.Indexed:
                        var indexedFileStructure = new IndexedFileStructure();
                        indexedFileStructure.RecordsOrganization = recordsOrganization;
                        indexedFileStructure.RecordKey = recordKey;
                        indexedFileStructure.Password = password;
                        indexedFileStructure.AlternateRecordKeys = alternateRecordKeys;
                        entry.Structure = indexedFileStructure;
                        break;
                    case FileRecordsOrganization.Relative:
                        var relativeFileStructure = new RelativeFileStructure();
                        relativeFileStructure.RecordsOrganization = recordsOrganization;
                        relativeFileStructure.RelativeKey = relativeKey;
                        relativeFileStructure.Password = password;
                        entry.Structure = relativeFileStructure;
                        break;
                }
            }

            Context = context;
            CodeElement = entry;
        }
        ////////////////////
        // PROCEDURE CALL //
        ////////////////////

        public override void EnterTcCallStatement(CodeElementsParser.TcCallStatementContext context)
        {
            var cbCallProc = context.procedurePointerOrFunctionPointerVariableOrfunctionNameReference;

            // Register call parameters (shared storage areas) information at the CodeElement level
            CallSite callSite = null;
            ProcedureStyleCallStatement statement = null;

            Context = context;

            //Incomplete CallStatement, create an empty CodeElement and return + Error due to issue #774
            if (cbCallProc == null)
            {
                CodeElement = new ProcedureStyleCallStatement
                {
                    Diagnostics = new List <Diagnostic>
                    {
                        new Diagnostic(MessageCode.SyntaxErrorInParser, context.Start.Column,
                                       context.Stop.Column, context.Start.Line, "Empty CALL is not authorized")
                    }
                };
                return;
            }


            //Here ambiguousSymbolReference with either CandidatesType:
            // - ProgramNameOrProgramEntry
            // - data, condition, UPSISwitch, TCFunctionName
            var ambiguousSymbolReference = CobolExpressionsBuilder.CreateProcedurePointerOrFunctionPointerVariableOrTCFunctionProcedure(cbCallProc);


            //If (inputs, inouts ou outputs).Count > 0, then it's a procedure call
            if (context.callOutputParameter().Length > 0 || context.callInputParameter().Length > 0 || context.callInoutParameter().Length > 0)
            {
                callSite = new CallSite();
                #region Setup Input Output Inout CallSitesParameters

                var inputs  = new List <CallSiteParameter>();
                var inouts  = new List <CallSiteParameter>();
                var outputs = new List <CallSiteParameter>();

                SyntaxProperty <ParameterSharingMode> mode = null;
                foreach (var p in context.callInputParameter())
                {
                    CreateSharingMode(p, ref mode); // TCRFUN_INPUT_BY
                    var callSiteParameter = new CallSiteParameter
                    {
                        SharingMode = mode,
                    };


                    if (p.sharedVariableOrFileName() != null)
                    {
                        callSiteParameter.StorageAreaOrValue = CobolExpressionsBuilder.CreateSharedVariableOrFileName(p.sharedVariableOrFileName());
                    }
                    else if (p.OMITTED() != null)
                    {
                        callSiteParameter.Omitted = new SyntaxProperty <bool>(true, ParseTreeUtils.GetFirstToken(p.OMITTED()));
                    }

                    if (p.sharedVariableOrFileName() != null || p.OMITTED() != null)
                    {
                        inputs.Add(callSiteParameter);
                    }
                }

                foreach (var p in context.callInoutParameter())
                {
                    var callSiteParameter = new CallSiteParameter
                    {
                        // TCRFUN_CALL_INOUT_AND_OUTPUT_BY_REFERENCE
                        SharingMode =
                            new SyntaxProperty <ParameterSharingMode>(ParameterSharingMode.ByReference, null),
                    };

                    if (p.sharedStorageArea1() != null)
                    {
                        callSiteParameter.StorageAreaOrValue = new Variable(CobolExpressionsBuilder.CreateSharedStorageArea(p.sharedStorageArea1()));
                    }
                    else if (p.OMITTED() != null)
                    {
                        callSiteParameter.Omitted = new SyntaxProperty <bool>(true, ParseTreeUtils.GetFirstToken(p.OMITTED()));
                    }

                    if (p.sharedStorageArea1() != null || p.OMITTED() != null)
                    {
                        inouts.Add(callSiteParameter);
                    }
                }

                foreach (var p in context.callOutputParameter())
                {
                    var callSiteParameter = new CallSiteParameter
                    {
                        // TCRFUN_CALL_INOUT_AND_OUTPUT_BY_REFERENCE
                        SharingMode =
                            new SyntaxProperty <ParameterSharingMode>(ParameterSharingMode.ByReference, null),
                    };

                    if (p.sharedStorageArea1() != null)
                    {
                        callSiteParameter.StorageAreaOrValue = new Variable(CobolExpressionsBuilder.CreateSharedStorageArea(p.sharedStorageArea1()));
                    }
                    else if (p.OMITTED() != null)
                    {
                        callSiteParameter.Omitted = new SyntaxProperty <bool>(true, ParseTreeUtils.GetFirstToken(p.OMITTED()));
                    }

                    if (p.sharedStorageArea1() != null || p.OMITTED() != null)
                    {
                        outputs.Add(callSiteParameter);
                    }
                }

                int parametersCount = inputs.Count + outputs.Count + inouts.Count;
                callSite.Parameters = new CallSiteParameter[parametersCount];
                int i = 0;

                //Add inputs to global callsites parameters
                if (inputs.Count > 0)
                {
                    foreach (var param in inputs)
                    {
                        callSite.Parameters[i] = param;
                        i++;
                    }
                }

                //Add outputs to global callsites parameters
                if (outputs.Count > 0)
                {
                    foreach (var param in outputs)
                    {
                        callSite.Parameters[i] = param;
                        i++;
                    }
                }

                //Add inouts to global callsites parameters
                if (inouts.Count > 0)
                {
                    foreach (var param in inouts)
                    {
                        callSite.Parameters[i] = param;
                        i++;
                    }
                }

                #endregion

                //Check Type or CandidatesTypes to see if a TCFunctionName is possible
                if (ambiguousSymbolReference.MainSymbolReference != null &&
                    ambiguousSymbolReference.MainSymbolReference.IsOrCanBeOfType(SymbolType.TCFunctionName))
                {
                    SymbolReferenceVariable TCFunctionNameRefVariable;

                    if (ambiguousSymbolReference.MainSymbolReference.IsQualifiedReference)
                    {
                        var nonAmbiguousHead =
                            new SymbolReference(
                                (ambiguousSymbolReference.MainSymbolReference as TypeCobolQualifiedSymbolReference)?.Head
                                .NameLiteral, SymbolType.TCFunctionName);
                        var nonAmbiguousTail =
                            new SymbolReference(
                                (ambiguousSymbolReference.MainSymbolReference as TypeCobolQualifiedSymbolReference)?.Tail
                                .NameLiteral, SymbolType.ProgramName);

                        TypeCobolQualifiedSymbolReference newQualifiedSymbolReferece =
                            new TypeCobolQualifiedSymbolReference(nonAmbiguousHead, nonAmbiguousTail);
                        TCFunctionNameRefVariable = new SymbolReferenceVariable(StorageDataType.MethodName,
                                                                                newQualifiedSymbolReferece);
                    }
                    else
                    {
                        //If so, create ProcedureStyleCallStatement with a ProcedureCall and fix SymbolReference so it's not ambiguous
                        var nonAmbiguousSymbolRef =
                            new SymbolReference(ambiguousSymbolReference.MainSymbolReference.NameLiteral,
                                                SymbolType.TCFunctionName);
                        TCFunctionNameRefVariable = new SymbolReferenceVariable(StorageDataType.MethodName,
                                                                                nonAmbiguousSymbolRef);
                    }

                    //CobolExpressionsBuilder store every StorageArea created into storageAreaReads and then after
                    //storageAreaReads is set to the CodeElement
                    //We must remove it as TCFunctionNameRefVariable doesn't contains a StorageArea
                    if (ambiguousSymbolReference.StorageArea != null)
                    {
                        CobolExpressionsBuilder.storageAreaReads.Remove(ambiguousSymbolReference.StorageArea);
                    }

                    statement =
                        new ProcedureStyleCallStatement(new ProcedureCall(TCFunctionNameRefVariable.MainSymbolReference,
                                                                          inputs, inouts, outputs))
                    {
                        ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction =
                            TCFunctionNameRefVariable.MainSymbolReference
                    };

                    callSite.CallTarget = TCFunctionNameRefVariable.MainSymbolReference;
                }
                else
                {
                    //else it's an error
                    statement =
                        new ProcedureStyleCallStatement(new ProcedureCall(ambiguousSymbolReference.MainSymbolReference,
                                                                          inputs, inouts, outputs))
                    {
                        ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction = ambiguousSymbolReference.MainSymbolReference,
                        Diagnostics = new List <Diagnostic>
                        {
                            new Diagnostic(MessageCode.ImplementationError, context.Start.Column,
                                           context.Stop.Column, context.Start.Line,
                                           "A call with arguments is not a TCFunctionName")
                        },
                    };

                    callSite.CallTarget = ambiguousSymbolReference.MainSymbolReference;
                }
            }
            else
            {
                if (ambiguousSymbolReference.MainSymbolReference != null &&
                    ambiguousSymbolReference.MainSymbolReference.IsOrCanBeOfType(SymbolType.DataName, SymbolType.TCFunctionName))
                {
                    //TODO think about uniformity of CandidateTypes inside QualifiedReference.
                    //Maybe just define CandidatesTypes for the Head...
                    if (ambiguousSymbolReference.MainSymbolReference.IsQualifiedReference)
                    {
                        var qualifiedSymbolReference = (QualifiedSymbolReference)ambiguousSymbolReference.MainSymbolReference;


                        AmbiguousSymbolReference.ApplyCandidatesTypes(qualifiedSymbolReference, new[] { SymbolType.DataName, SymbolType.ProgramName });
                        //Adjust candidate types only for the first element
                        if (qualifiedSymbolReference.First.IsAmbiguous)
                        {
                            ((AmbiguousSymbolReference)qualifiedSymbolReference.First).CandidateTypes = new[] { SymbolType.DataName, SymbolType.TCFunctionName };
                        }
                    }
                    else
                    {
                        ((AmbiguousSymbolReference)ambiguousSymbolReference.MainSymbolReference).CandidateTypes = new[] { SymbolType.DataName, SymbolType.TCFunctionName };
                    }

                    statement = new ProcedureStyleCallStatement(new ProcedureCall(ambiguousSymbolReference.MainSymbolReference,
                                                                                  null, null, null))
                    {
                        ProcdurePointerOrTCProcedureFunction = ambiguousSymbolReference.MainSymbolReference
                    };
                    callSite            = new CallSite();
                    callSite.CallTarget = statement.ProcdurePointerOrTCProcedureFunction;
                }
                else     //else, it's an error
                {
                    statement =
                        new ProcedureStyleCallStatement(new ProcedureCall(ambiguousSymbolReference.MainSymbolReference,
                                                                          null, null, null))
                    {
                        ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction =
                            ambiguousSymbolReference.MainSymbolReference,
                    };
                    statement.Diagnostics.Add(new Diagnostic(MessageCode.SyntaxErrorInParser, context.Start.Column,
                                                             context.Stop.Column, context.Start.Line, "Error in detecting Procedure Call type"));
                    callSite            = new CallSite();
                    callSite.CallTarget = statement.ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction;
                }
            }


            if (callSite != null)
            {
                if (statement.CallSites == null)
                {
                    statement.CallSites = new List <CallSite>();
                }
                statement.CallSites.Add(callSite);
            }

            CodeElement = statement;
        }
 public TableSortingKey(SymbolReference sortKey, SyntaxProperty<SortDirection> sortDirection)
 {
     SortKey = sortKey;
     SortDirection = sortDirection;
 }
Beispiel #21
0
        public static string PrettyPrint(string path)
        {
            var text    = File.ReadAllText(path);
            var grammar = new ObjectGrammar();
            var parser  = new Parser(grammar);


            var parseTree = parser.Parse(text);

            if (parseTree.Status == ParseTreeStatus.Error)
            {
                var sb = new StringBuilder();
                foreach (var msg in parseTree.ParserMessages)
                {
                    sb.AppendLine($"{msg.Message} at location: {msg.Location.ToUiString()}");
                }
                throw new DataParserException($"Parsing failed:\n\n{sb.ToString()}");
            }
            else
            {
                var root = new SyntaxRoot();

                int i = 0;
                while (i < parseTree.Tokens.Count)
                {
                    if (parseTree.Tokens[i].Category == TokenCategory.Comment)
                    {
                        root.Elements.Add(new SyntaxComment()
                        {
                            Text = parseTree.Tokens[i].Text
                        });
                    }


                    if (parseTree.Tokens[i].Terminal.Name.ToLower() == "object")
                    {
                        i++;

                        SyntaxObject obj = new SyntaxObject()
                        {
                            Name = parseTree.Tokens[i].Text
                        };
                        i++;

                        if (parseTree.Tokens[i].Text == "[")
                        {
                            i++;

                            string prefix = "";
                            while (parseTree.Tokens[i].Terminal.Name != "]")
                            {
                                if (parseTree.Tokens[i].Terminal.Name == "comma")
                                {
                                    i++;
                                }

                                obj.Attributes += $"{prefix} {parseTree.Tokens[i].Text.Trim()}";
                                i++;

                                if (parseTree.Tokens[i].Terminal.Name == "=")
                                {
                                    obj.Attributes += " = ";
                                    i++;
                                    obj.Attributes += parseTree.Tokens[i].Text;
                                    i++;
                                }

                                prefix = ",";
                            }
                            i++;
                            obj.Attributes = "[" + obj.Attributes.Trim() + "]";
                        }
                        int headerLine = parseTree.Tokens[i].Location.Line;
                        i++;

                        while (parseTree.Tokens[i].Text != "}")
                        {
                            if (parseTree.Tokens[i].Category == TokenCategory.Comment)
                            {
                                if (headerLine == parseTree.Tokens[i].Location.Line)
                                {
                                    obj.HeaderComment = parseTree.Tokens[i].Text;
                                }
                                else
                                {
                                    obj.Elements.Add(new SyntaxComment()
                                    {
                                        Text = parseTree.Tokens[i].Text
                                    });
                                }
                            }

                            if (parseTree.Tokens[i].Terminal.Name.ToLower() == "identifier" || parseTree.Tokens[i].Terminal.Name.ToLower() == "?")
                            {
                                SyntaxProperty prop = new SyntaxProperty()
                                {
                                    Optional = (parseTree.Tokens[i].Terminal.Name.ToLower() == "?"),
                                    Name     = parseTree.Tokens[i + ((parseTree.Tokens[i].Terminal.Name.ToLower() == "?") ? 1 : 0)].Text
                                };

                                int propLine = parseTree.Tokens[i].Location.Line;

                                if (prop.Optional)
                                {
                                    i++;
                                }
                                i++;
                                i++;
                                if (parseTree.Tokens[i].Terminal.Name.ToLower() == "list")
                                {
                                    prop.List = true;
                                    i++;
                                }
                                prop.Type = parseTree.Tokens[i].Text;
                                i++;

                                if (parseTree.Tokens[i].Terminal.Name == "=")
                                {
                                    i++;
                                    prop.Default  = parseTree.Tokens[i].Text;
                                    prop.Optional = true;
                                    i++;
                                }

                                if (parseTree.Tokens[i].Terminal.Name == "[")
                                {
                                    i++;

                                    string prefix = "";
                                    while (parseTree.Tokens[i].Terminal.Name != "]")
                                    {
                                        if (parseTree.Tokens[i].Terminal.Name == "comma")
                                        {
                                            i++;
                                        }

                                        prop.Attributes += $"{prefix} {parseTree.Tokens[i].Text.Trim()}";
                                        i++;

                                        if (parseTree.Tokens[i].Terminal.Name == "=")
                                        {
                                            prop.Attributes += " = ";
                                            i++;
                                            prop.Attributes += parseTree.Tokens[i].Text;
                                            i++;
                                        }

                                        prefix = ",";
                                    }
                                    i++;
                                    prop.Attributes = "[" + prop.Attributes.Trim() + "]";
                                }

                                if (parseTree.Tokens[i].Category == TokenCategory.Comment)
                                {
                                    if (parseTree.Tokens[i].Location.Line == propLine)
                                    {
                                        prop.Comment = parseTree.Tokens[i].Text;
                                        obj.Elements.Add(prop);
                                    }
                                    else
                                    {
                                        obj.Elements.Add(prop);
                                        obj.Elements.Add(new SyntaxComment()
                                        {
                                            Text = parseTree.Tokens[i].Text
                                        });
                                    }
                                    i++;
                                }
                                else
                                {
                                    obj.Elements.Add(prop);
                                }
                            }
                        }
                        if (parseTree.Tokens[i + 1].Category == TokenCategory.Comment)
                        {
                            if (parseTree.Tokens[i].Location.Line == parseTree.Tokens[i + 1].Location.Line)
                            {
                                obj.FooterComment = parseTree.Tokens[i + 1].Text;
                                root.Elements.Add(obj);
                            }
                            else
                            {
                                root.Elements.Add(obj);
                                root.Elements.Add(new SyntaxComment()
                                {
                                    Text = parseTree.Tokens[i + 1].Text
                                });
                            }
                            i++;
                        }
                        else
                        {
                            root.Elements.Add(obj);
                        }
                    }

                    if (parseTree.Tokens[i].Terminal.Name.ToLower() == "external")
                    {
                        i++;
                        SyntaxExternalType ext = new SyntaxExternalType()
                        {
                            Name = parseTree.Tokens[i].Text
                        };
                        i++;
                        if (parseTree.Tokens[i].Terminal.Name == "[")
                        {
                            i++;

                            string prefix = "";
                            while (parseTree.Tokens[i].Terminal.Name != "]")
                            {
                                if (parseTree.Tokens[i].Terminal.Name == "comma")
                                {
                                    i++;
                                }

                                ext.Attributes += $"{prefix} {parseTree.Tokens[i].Text.Trim()}";
                                i++;

                                if (parseTree.Tokens[i].Terminal.Name == "=")
                                {
                                    ext.Attributes += " = ";
                                    i++;
                                    ext.Attributes += parseTree.Tokens[i].Text;
                                    i++;
                                }

                                prefix = ",";
                            }
                            i++;
                            ext.Attributes = "[" + ext.Attributes.Trim() + "]";
                        }

                        if (parseTree.Tokens[i].Category == TokenCategory.Comment)
                        {
                            ext.Comment = parseTree.Tokens[i].Text;
                            i++;
                        }
                        root.Elements.Add(ext);
                    }

                    i++;
                }

                var result = new StringBuilder();

                foreach (var element in root.Elements)
                {
                    if (element is SyntaxComment comment)
                    {
                        result.AppendLine(comment.Text.Trim());
                    }
                    else if (element is SyntaxObject obj)
                    {
                        if (string.IsNullOrWhiteSpace(obj.Attributes))
                        {
                            result.Append($"object {obj.Name.Trim()} {{");
                        }
                        else
                        {
                            result.Append($"object {obj.Name.Trim()} {obj.Attributes.Trim()} {{");
                        }

                        if (!string.IsNullOrWhiteSpace(obj.HeaderComment.Trim()))
                        {
                            result.AppendLine($" {obj.HeaderComment.Trim()}");
                        }
                        else
                        {
                            result.AppendLine();
                        }

                        var props = obj.Elements.Where(e => e is SyntaxProperty).Select(e => (SyntaxProperty)e);

                        var nameLength    = props.Max(p => p.Name.Length + (p.Optional ? 2 : 0));
                        var typeLength    = props.Max(p => p.Type.Length + (p.List ? 5 : 0));
                        var defaultLength = props.Max(p => p.Default.Trim().Length);
                        var hasDefault    = props.Any(p => !string.IsNullOrWhiteSpace(p.Default));
                        var attrLength    = props.Max(p => p.Attributes.Length);

                        foreach (var innerElement in obj.Elements)
                        {
                            if (innerElement is SyntaxComment innerComment)
                            {
                                result.AppendLine("  " + innerComment.Text.Trim());
                            }
                            else if (innerElement is SyntaxProperty p)
                            {
                                var propString = new StringBuilder();
                                if (p.Optional)
                                {
                                    propString.Append($"? {p.Name}".PadRight(nameLength));
                                }
                                else
                                {
                                    propString.Append($"{p.Name}".PadRight(nameLength));
                                }
                                propString.Append(" : ");
                                if (p.List)
                                {
                                    propString.Append($"List {p.Type}".PadRight(typeLength));
                                }
                                else
                                {
                                    propString.Append($"{p.Type}".PadRight(typeLength));
                                }

                                if (!string.IsNullOrWhiteSpace(p.Default.Trim()))
                                {
                                    propString.Append(" = ");
                                    propString.Append(p.Default.Trim().PadRight(defaultLength));
                                }
                                else
                                {
                                    propString.Append("".PadRight(defaultLength + (hasDefault ? 3 : 0)));
                                }
                                if (attrLength > 0)
                                {
                                    propString.Append($" {p.Attributes.PadRight(attrLength)}");
                                }
                                propString.Append(" " + p.Comment);
                                result.AppendLine("  " + propString.ToString().Trim());
                            }
                        }

                        if (!string.IsNullOrWhiteSpace(obj.FooterComment))
                        {
                            result.AppendLine($"}} {obj.FooterComment.Trim()}");
                        }
                        else
                        {
                            result.AppendLine($"}}");
                        }
                        result.AppendLine();
                    }
                }


                foreach (var element in root.Elements)
                {
                    if (element is SyntaxExternalType ext)
                    {
                        if (string.IsNullOrWhiteSpace(ext.Attributes))
                        {
                            result.Append($"external {ext.Name.Trim()}");
                        }
                        else
                        {
                            result.Append($"external {ext.Name.Trim()} {ext.Attributes.Trim()}");
                        }

                        if (!string.IsNullOrWhiteSpace(ext.Comment.Trim()))
                        {
                            result.AppendLine($" {ext.Comment.Trim()}");
                        }
                        else
                        {
                            result.AppendLine();
                        }
                    }
                }
                //result.AppendLine();

                return(result.ToString());
            }
        }