001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2005-2006 Princeton University
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.lang.c4;
020:
021: import xtc.lang.CParserState;
022: import java.util.HashMap;
023:
024: /**
025: * State for parsing C4.
026: *
027: * @author Marco Yuen
028: * @version $Revision: 1.2 $
029: */
030: public class C4ParserState extends CParserState {
031:
032: /** The name of the current aspect in context. */
033: private String curAspectName = null;
034:
035: /** The binding of aspect and context. */
036: private HashMap aspectContextBindings = null;
037:
038: /** The flag for indicating the current context is inside an advice. */
039: public static final int FLAG_ADVICE = 0x40;
040:
041: public C4ParserState() {
042: super ();
043: this .aspectContextBindings = new HashMap();
044: }
045:
046: /**
047: * Set the FLAG_ADVICE flag and current aspectName in the current context.
048: *
049: * @param aspectName The name of the current aspect
050: */
051: public void setAdvice(String aspectName) {
052: top.set(FLAG_ADVICE);
053: curAspectName = aspectName;
054: if (DEBUG)
055: System.out.println("Setting curAspectName to "
056: + curAspectName);
057: }
058:
059: /**
060: * Bind the specified identifier. Depending on the current parsing
061: * context, the identifier is either bound as a type or as an
062: * object/function/constant.
063: *
064: * @param id The identifier.
065: */
066: public void bind(String id) {
067: // Ignore the binding if a function parameter list has already
068: // been parsed or the binding appears inside a structure
069: // declaration list.
070: if (top.next.isSet(FLAG_PARAMS)
071: || top.next.isSet(FLAG_STRUCTURE)) {
072: if (DEBUG) {
073: System.out.println("ignoring bind(" + id + ", "
074: + top.isSet(FLAG_TYPEDEF) + ")");
075: }
076: return;
077: } else if (DEBUG) {
078: System.out.println("bind(" + id + ", "
079: + top.isSet(FLAG_TYPEDEF) + ")");
080: }
081:
082: // Get the top-most scope.
083: Context c = top;
084: while (!c.isSet(FLAG_SCOPE)) {
085: c = c.next;
086: }
087:
088: if (c.isSet(FLAG_ADVICE)) {
089: if (DEBUG)
090: System.out.println("BIND: binding " + id
091: + " in aspect context: " + curAspectName
092: + " <--------");
093:
094: if (!aspectContextBindings.containsKey(curAspectName))
095: aspectContextBindings.put(curAspectName, new HashMap());
096:
097: ((HashMap) aspectContextBindings.get(curAspectName)).put(
098: id, top.isSet(FLAG_TYPEDEF) ? Boolean.TRUE
099: : Boolean.FALSE);
100:
101: if (DEBUG)
102: System.out.println("------- Aspect Bindings -------\n"
103: + aspectContextBindings
104: + "\n------- Aspect Bindings -------");
105: }
106:
107: // Record the name.
108: c.bindings.put(id, top.isSet(FLAG_TYPEDEF) ? Boolean.TRUE
109: : Boolean.FALSE);
110: c.set(FLAG_MODIFIED);
111: }
112:
113: /**
114: * Determine whether the specified identifier names a type.
115: *
116: * @param id The identifier.
117: * @return <code>true</code> if the specified identifier names a type.
118: */
119: public boolean isType(String id) {
120: // If we have already parsed a type specifier, the identifier does
121: // not name a type.
122: if (top.isSet(FLAG_TYPE_SPEC)) {
123: if (DEBUG)
124: System.out.println("isType(" + id + ") -> false");
125: return false;
126: }
127:
128: // Otherwise, we consult the symbol table.
129: Context c = top;
130:
131: do {
132: while (!c.isSet(FLAG_SCOPE)) {
133: c = c.next;
134: }
135:
136: Object value = c.bindings.get(id);
137: if (null != value) {
138: boolean type = ((Boolean) value).booleanValue();
139: if (DEBUG)
140: System.out.println("isType(" + id + ") -> " + type);
141: return type;
142: }
143:
144: if (c.isSet(FLAG_ADVICE)
145: && aspectContextBindings.containsKey(curAspectName)) {
146: if (DEBUG)
147: System.out
148: .println("Consulting the aspect bindings table for aspect '"
149: + curAspectName
150: + "' and id '"
151: + id
152: + "' <-------");
153: value = ((HashMap) aspectContextBindings
154: .get(curAspectName)).get(id);
155: if (null != value) {
156: boolean type = ((Boolean) value).booleanValue();
157: if (DEBUG)
158: System.out.println("aspect bindings:isType("
159: + id + ") -> " + type);
160: return type;
161: }
162: }
163:
164: c = c.next;
165: } while (null != c);
166:
167: if (DEBUG)
168: System.out.println("isType(" + id + ") -> false");
169: return false;
170: }
171: }
172:
173: // vim: set sts=2 sw=2 et :
|