|
1 /* |
|
2 * Copyright (c) 2004-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 using System; |
|
19 using System.Text; |
|
20 using SymBuildParsingLib.Tree; |
|
21 using SymBuildParsingLib.Token; |
|
22 using SymBuildParsingLib.Common.Objects; |
|
23 using SymBuildParsingLib.Parser.Framework.Parser; |
|
24 using SymBuildParsingLib.Parser.Framework.Workers; |
|
25 using SymBuildParsingLib.Parser.Framework.Document; |
|
26 using SymBuildParsingLib.Parser.PreProcessor.Nodes; |
|
27 |
|
28 namespace SymBuildParsingLib.Parser.PreProcessor.Workers |
|
29 { |
|
30 public sealed class SymPreProcessorWorkerInclude : SymParserWorkerConsumer |
|
31 { |
|
32 #region Constructors & destructor |
|
33 public SymPreProcessorWorkerInclude( SymParserWorkerContext aContext ) |
|
34 : base( aContext, SymToken.TClass.EClassNewLine, SymParserWorkerConsumer.TDyingAction.EWhenDyingMakeAbsoluteParentNodeCurrent ) |
|
35 { |
|
36 // Make a new child node for the include |
|
37 iIncludeNode = new SymNodePreProcessorInclude(); |
|
38 aContext.Document.CurrentNode.Add( iIncludeNode ); |
|
39 aContext.Document.CurrentNode = iIncludeNode; |
|
40 } |
|
41 #endregion |
|
42 |
|
43 #region From SymParserWorkerConsumer |
|
44 protected override void HandleTerminatingConditionMatch( SymToken aToken ) |
|
45 { |
|
46 // Update the include so that it contains a fully resolved path |
|
47 iIncludeNode.IncludeDefinition.AdjustRelativeInclude( WorkerContext.Parser.FileName ); |
|
48 |
|
49 // We've now a fully resolved file name which we can parse, should |
|
50 // we desire... |
|
51 string includeFile = iIncludeNode.IncludeDefinition.Location; |
|
52 if ( Utils.SymFileSystemUtils.FileExists( includeFile ) ) |
|
53 { |
|
54 // Make a new document context |
|
55 SymParserDocumentContext subDocumentContext = new SymParserDocumentContext( includeFile, WorkerContext ); |
|
56 |
|
57 // Use the existing document, but with a new context |
|
58 WorkerContext.Document.PushContext( subDocumentContext ); |
|
59 |
|
60 // Make a new carbon copy of this parser (whatever concrete type it may be) |
|
61 SymParserBase subParser = WorkerContext.Parser.CarbonCopy( new object[] { WorkerContext.Document } ); |
|
62 |
|
63 // Make the waiting object |
|
64 SymParserWaiter waiter = new SymParserWaiter( subParser ); |
|
65 |
|
66 // Now parse the file and wait for the result |
|
67 subParser.Parse(); |
|
68 waiter.Wait(); |
|
69 |
|
70 // Restore the original context |
|
71 WorkerContext.Document.PopContext(); |
|
72 } |
|
73 } |
|
74 #endregion |
|
75 |
|
76 #region From SymParserWorker |
|
77 public override SymParserWorker.TTokenConsumptionType OfferToken( SymToken aToken ) |
|
78 { |
|
79 TTokenConsumptionType ret = TTokenConsumptionType.ETokenNotConsumed; |
|
80 System.Diagnostics.Debug.Assert( WorkerContext.Document.CurrentNode is SymNodePreProcessorInclude ); |
|
81 |
|
82 // Only consume tokens whilst we're unsure of the include type (system vs user). |
|
83 if ( iIncludeNode.IncludeDefinition.Type == SymIncludeDefinition.TType.ETypeUndefined ) |
|
84 { |
|
85 if ( aToken.Class == SymToken.TClass.EClassQuotation ) |
|
86 { |
|
87 // Must be a user include if its a quotation that we're handling |
|
88 iIncludeNode.IncludeDefinition.Type = SymIncludeDefinition.TType.ETypeUser; |
|
89 ret = TTokenConsumptionType.ETokenConsumed; |
|
90 } |
|
91 else if ( aToken.Class == SymToken.TClass.EClassSymbol && aToken.Value == "<" ) |
|
92 { |
|
93 // Consume it, but don't absorb it |
|
94 iIncludeNode.IncludeDefinition.Type = SymIncludeDefinition.TType.ETypeSystem; |
|
95 ret = TTokenConsumptionType.ETokenConsumed; |
|
96 } |
|
97 } |
|
98 else if ( iIncludeNode.IncludeDefinition.Type != SymIncludeDefinition.TType.ETypeUndefined ) |
|
99 { |
|
100 // Only consume the tokens whilst we've not yet identified the include |
|
101 // definition location. |
|
102 if ( iIncludeNode.IncludeDefinition.Location.Length == 0 ) |
|
103 { |
|
104 if ( iIncludeNode.IncludeDefinition.Type == SymIncludeDefinition.TType.ETypeSystem && aToken.Class == SymToken.TClass.EClassSymbol && aToken.Value == ">" ) |
|
105 { |
|
106 iIncludeNode.IncludeDefinition.Location = iWorkingIncludePath.ToString(); |
|
107 } |
|
108 else if ( iIncludeNode.IncludeDefinition.Type == SymIncludeDefinition.TType.ETypeUser && aToken.Class == SymToken.TClass.EClassQuotation && aToken.Type != SymToken.TType.ETypeUnidentified ) |
|
109 { |
|
110 iIncludeNode.IncludeDefinition.Location = iWorkingIncludePath.ToString(); |
|
111 } |
|
112 else |
|
113 { |
|
114 iWorkingIncludePath.Append( aToken.Value ); |
|
115 } |
|
116 } |
|
117 } |
|
118 |
|
119 // Base class will dequeue us once we reach the new line |
|
120 ret = base.OfferToken( aToken ); |
|
121 return ret; |
|
122 } |
|
123 #endregion |
|
124 |
|
125 #region Data members |
|
126 private StringBuilder iWorkingIncludePath = new StringBuilder(); |
|
127 private readonly SymNodePreProcessorInclude iIncludeNode; |
|
128 #endregion |
|
129 } |
|
130 } |