1
/*******************************************************************************
2
* Copyright (c) 2006, 2009 IBM Corporation and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* IBM Corporation - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.internal.core.dom.lrparser.c99.action.deprecated;
13
import java.util.LinkedList;
15
import lpg.lpgjavaruntime.IToken;
17
import org.eclipse.cdt.core.dom.lrparser.action.ITokenStream;
18
import org.eclipse.cdt.core.parser.util.DebugUtil;
19
import org.eclipse.cdt.internal.core.dom.lrparser.symboltable.TypedefSymbolTable;
21
* A simple set of trial and undo actions that just keep track
22
* of typedef names. This information is then fed back to the parser
23
* in order to disambiguate certain parser grammar rules.
25
* The command design pattern is used to implement undo actions.
29
public class C99TypedefTrackerParserAction {
31
private static final boolean DEBUG = true;
34
// provides limited access to the token stream
35
private final ITokenStream parser;
37
// The symbolTable currently in use
38
private TypedefSymbolTable symbolTable = TypedefSymbolTable.EMPTY_TABLE;
40
// A stack that keeps track of scopes in the symbol table, used to "close" scopes and to undo the opening of scopes
41
private final LinkedList<TypedefSymbolTable> symbolTableScopeStack = new LinkedList<TypedefSymbolTable>();
43
// keeps track of nested declarations
44
private final LinkedList<DeclaratorFrame> declarationStack = new LinkedList<DeclaratorFrame>();
47
// "For every action there is an equal and opposite reaction." - Newton's third law
48
private final LinkedList<IUndoAction> undoStack = new LinkedList<IUndoAction>();
52
* A command object that provides undo functionality.
54
private interface IUndoAction {
60
* Undoes the last fired action.
63
undoStack.removeLast().undo();
67
public C99TypedefTrackerParserAction(ITokenStream parser) {
73
* Lexer feedback hack, used by the parser to identify typedefname tokens.
75
public boolean isTypedef(String ident) {
76
return symbolTable.contains(ident);
81
* Methods used by tests, package local access.
83
TypedefSymbolTable getSymbolTable() {
88
return undoStack.size();
91
LinkedList<DeclaratorFrame> getDeclarationStack() {
92
return declarationStack;
97
* Called from the grammar file in places where a scope is created.
99
* Scopes are created by compound statements, however special care
100
* must also be taken with for loops because they may contain
103
* TODO: scope object now need to be handled explicitly
105
public void openSymbolScope() {
106
if(DEBUG) DebugUtil.printMethodTrace();
108
symbolTableScopeStack.add(symbolTable);
110
undoStack.add(new IUndoAction() {
112
if(DEBUG) DebugUtil.printMethodTrace();
114
symbolTable = symbolTableScopeStack.removeLast();
120
public void closeSymbolScope() {
121
if(DEBUG) DebugUtil.printMethodTrace();
123
final TypedefSymbolTable undoTable = symbolTable;
124
symbolTable = symbolTableScopeStack.removeLast(); // close the scope
126
undoStack.add(new IUndoAction() {
128
if(DEBUG) DebugUtil.printMethodTrace();
130
symbolTableScopeStack.add(symbolTable);
131
symbolTable = undoTable;
139
* Called from the grammar before a declaration is about to be reduced.
141
public void openDeclarationScope() {
142
if(DEBUG) DebugUtil.printMethodTrace();
144
declarationStack.add(new DeclaratorFrame());
146
undoStack.add(new IUndoAction() {
148
if(DEBUG) DebugUtil.printMethodTrace();
150
declarationStack.removeLast();
156
public void closeDeclarationScope() {
157
if(DEBUG) DebugUtil.printMethodTrace();
159
final DeclaratorFrame undoFrame = declarationStack.removeLast();
161
undoStack.add(new IUndoAction() {
163
if(DEBUG) DebugUtil.printMethodTrace();
165
declarationStack.add(undoFrame);
171
public void consumeFunctionDefinition() {
172
if(DEBUG) DebugUtil.printMethodTrace();
174
final DeclaratorFrame frame = declarationStack.removeLast();
176
final TypedefSymbolTable undoTable = symbolTable;
177
symbolTable = symbolTableScopeStack.removeLast();
180
undoStack.add(new IUndoAction() {
182
if(DEBUG) DebugUtil.printMethodTrace();
184
symbolTableScopeStack.add(symbolTable);
185
symbolTable = undoTable;
187
declarationStack.add(frame);
195
public void consumeDeclSpecToken() {
196
if(DEBUG) DebugUtil.printMethodTrace();
198
IToken token = parser.getRightIToken();
199
final int kind = token.getKind();
201
// creates a DeclSpec if there isn't one already
202
DeclaratorFrame frame = declarationStack.getLast();
203
final DeclSpec declSpec = frame.getDeclSpec();
206
undoStack.add(new IUndoAction() {
208
if(DEBUG) DebugUtil.printMethodTrace();
210
declSpec.remove(kind);
217
public void consumeDirectDeclaratorIdentifier() {
218
if(DEBUG) DebugUtil.printMethodTrace();
220
final DeclaratorFrame frame = declarationStack.getLast();
221
frame.setDeclaratorName(parser.getRightIToken());
223
undoStack.add(new IUndoAction() {
225
if(DEBUG) DebugUtil.printMethodTrace();
227
frame.setDeclaratorName(null);
233
public void consumeDeclaratorComplete() {
234
if(DEBUG) DebugUtil.printMethodTrace();
236
final DeclaratorFrame frame = declarationStack.getLast();
238
IToken token = frame.getDeclaratorName();
239
DeclSpec declSpec = frame.getDeclSpec();
241
String ident = (token == null) ? null : token.toString();
242
//System.out.println("declarator complete: " + ident);
244
final TypedefSymbolTable oldTable = symbolTable;
245
if(declSpec.isTypedef()) {
246
//System.out.println("adding typedef: " + ident);
247
symbolTable = symbolTable.add(ident);
250
declarationStack.removeLast();
251
declarationStack.add(new DeclaratorFrame(frame.getDeclSpec())); // reset the declarator
253
undoStack.add(new IUndoAction() {
255
if(DEBUG) DebugUtil.printMethodTrace();
257
declarationStack.removeLast();
258
declarationStack.add(frame);
259
symbolTable = oldTable;
267
public void consumeDeclaratorCompleteParameter() {
268
if(DEBUG) DebugUtil.printMethodTrace();
270
final DeclaratorFrame frame = declarationStack.removeLast();
272
//declarationStack.getLast().addNestedDeclaration(parameterBinding);
274
// parameter declarations can only have one declarator, so don't reset
275
//declarationStack.add(new DeclaratorFrame()); // reset
278
undoStack.add(new IUndoAction() {
280
if(DEBUG) DebugUtil.printMethodTrace();
281
//declarationStack.removeLast();
282
//declarationStack.getLast().removeLastNestedDeclaration();
283
declarationStack.add(frame);
290
* This is a special case for the rule:
291
* parameter_declaration ::= declaration_specifiers
293
* In this case there is no declarator at all
295
* TODO: creating bindings that have no identifier seems really dumb,
296
* why does it need to be done? Why not just have a null binding or
297
* for that matter don't even have a name node
300
public void consumeParameterDeclarationWithoutDeclarator() {
301
if(DEBUG) DebugUtil.printMethodTrace();
303
final DeclaratorFrame frame = declarationStack.removeLast();
305
undoStack.add(new IUndoAction() {
307
if(DEBUG) DebugUtil.printMethodTrace();
309
declarationStack.add(frame);
315
public void consumeDeclaratorCompleteField() {
316
if(DEBUG) DebugUtil.printMethodTrace();
318
final DeclaratorFrame frame = declarationStack.removeLast();
320
declarationStack.add(new DeclaratorFrame(frame.getDeclSpec())); // reset the declarator
322
undoStack.add(new IUndoAction() {
324
if(DEBUG) DebugUtil.printMethodTrace();
326
declarationStack.removeLast();
328
declarationStack.add(frame);
335
* An abstract declarator used as part of an expression, eg) a cast.
336
* Only need the type.
338
* TODO: this isn't enough, I need a binding for the abstract declarator
339
* what I really need is a consumeDeclaratorCompleteTypeId similar to above
341
public void consumeTypeId() {
342
if(DEBUG) DebugUtil.printMethodTrace();
344
final DeclaratorFrame frame = declarationStack.removeLast();
346
undoStack.add(new IUndoAction() {
348
if(DEBUG) DebugUtil.printMethodTrace();
350
declarationStack.add(frame);