⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parsergen.java

📁 cocorj09-一个Java语言分析器
💻 JAVA
字号:
package Coco;

import java.io.*;
import java.util.*;

class ParserGen {

	static final int maxSymSets = 128;  // max. nr. of symbol sets
	static final int maxTerm = 3;       // sets of size < maxTerm are enumerated
	static final int maxAlter = 5;      // more than MaxAlter alternatives handled with case
	static final char CR  = '\r';
	static final char LF  = '\n';
	static final char TAB = '\t';
	static final char EOF = '\uffff';

	static final int tErr = 0;          // error codes
	static final int altErr = 1;
	static final int syncErr = 2;

	static int maxSS;                   // number of symbol sets
	static int errorNr;                 // highest parser error number
	static int curSy;                   // symbol whose production is currently generated
	static StringBuffer err;            // generated parser error messages
	static String srcDir;               // directory of attribute grammar file
	static BitSet[] symSet;

// Portability - Use the following for Java 1.0
//	static InputStream fram;            // parser frame file            Java 1.0
//	static PrintStream gen;             // generated parser source file Java 1.0

// Portability - Use the following for Java 1.1
//	static Reader fram;                 // parser frame file            Java 1.1
//	static PrintWriter gen;             // generated parser source file Java 1.1

	static Reader fram;                 // parser frame file            Java 1.1
	static PrintWriter gen;             // generated parser source file Java 1.1

	static private String Int(int n, int len) {
		String s = String.valueOf(n);
		int i = s.length(); if (len < i) len = i;
		int j = 0, d = len - s.length();
		char[] a = new char[len];
		for (i=0; i<d; i++) a[i] = ' ';
		for (j=0; i<len; i++) {a[i] = s.charAt(j); j++;}
		return new String(a, 0, len);
	}

	private static void Indent(int n) {
		for (int i=1; i<=n; i++) gen.print('\t');
	}

	private static int Alternatives (int p) {
		int i = 0;
		while (p > 0) {
			i++; p = Tab.Node(p).p2;
		}
		return i;
	}

	private static void CopyFramePart(String stop) {
		int ch, i;
		int last = 0;
		int startCh = stop.charAt(0);
		int high = stop.length() - 1;
		try {
			ch = fram.read();
			while (ch!=EOF)
				if (ch==startCh) {
					i = 0;
					do {
						if (i==high) return; // stop[0..i] found
						ch = fram.read(); i++;
					} while (ch==stop.charAt(i));
					// stop[0..i-1] found; continue with last read character
					gen.print(stop.substring(0, i));
				} else if (ch==LF) { if (last!=CR)gen.println(); last = ch; ch = fram.read();
				} else if (ch==CR) { gen.println(); last = ch; ch = fram.read();
				} else {
					gen.print((char)ch); last = ch; ch = fram.read();
				}
		} catch (IOException e) {
			Scanner.err.Exception("-- error reading Parser.frame");
		}
	}

	private static void CopySourcePart(Position pos, int indent) {
		// Copy text described by pos from atg to gen
		int ch, lastCh, nChars, i, col;
		if (pos != null) {
			Buffer.Set(pos.beg);
			ch = ' ';
			nChars = pos.len;
			col = pos.col - 1;
			while (nChars > 0 && (ch == ' ' || ch == '\t') ) {
			// skip over leading white space
				ch = Buffer.read(); nChars--; col++;
			}
			Indent(indent);
			loop:
			for (;;) {
				while (ch == CR || ch == LF) {
					// blank lines with correct number of leading blanks
					gen.println();
					lastCh = ch;
					if (nChars > 0) { ch = Buffer.read(); nChars--;  } else break loop;
					if ((ch == '\n') && (lastCh == '\r')) { // must be MS-DOS
						if (nChars > 0) { ch = Buffer.read(); nChars--; } else break loop;
					}
					if (ch != CR && ch != LF) { // there must be something on this line
						Indent(indent);
						i = col - 1;
						while ((ch == ' ' || ch == '\t') && i > 0) {
						// skip at most "col - 1" white space at line start
							if (nChars > 0) { ch = Buffer.read(); nChars--; } else break loop;
							i--;
						}
					}
				}
				i = 0;
				while (ch == ' ') {
					if (nChars > 0) { ch = Buffer.read(); nChars--; } else break loop;
					i++;
				}
				if (ch != CR && ch != LF && ch != EOF)  {
					for (int j = 1; j <= i; j++) gen.print(' ');
					gen.print((char) ch);
					if (nChars > 0) { ch = Buffer.read(); nChars--; } else break loop;
				}
			}
			if (indent > 0) gen.println();
		}
	}

/* old was
	private static void CopySourcePart(Position pos, int indent) {
		// Copy text described by pos from atg to gen
		int ch, nChars, i;
		if (pos != null) {
			Buffer.Set(pos.beg); ch = Buffer.read(); nChars = pos.len - 1;
			Indent(indent);
			loop:
			while (nChars >= 0) {
				while (ch==CR) {
					gen.println(); Indent(indent);
					ch = Buffer.read(); nChars--;
					for (i=1; i<=pos.col && ch<=' '; i++) { // skip blanks at beginning of line
						ch = Buffer.read(); nChars--;
					}
					if (i <= pos.col) pos.col = i - 1; // heading TABs => not enough blanks
					if (nChars < 0) break loop;
				}
				gen.print((char)ch);
				ch = Buffer.read(); nChars--;
			}
			if (indent > 0) gen.println();
		}
	}
*/

	private static void PrintTermName(int n) {
		if (Tab.sy[n].symName == null) gen.print(n);
		else gen.print("SYM." + Tab.sy[n].symName);
	}

	private static void GenErrorMsg(int errTyp, int errSym) {
		errorNr++;
		String name = Tab.Sym(errSym).name.replace('"', '\'');
		err.append("\t\t\tcase " + errorNr + ": {s = \"");
		switch (errTyp) {
			case tErr: {err.append(name + " expected"); break;}
			case altErr: {err.append("invalid " + name); break;}
			case syncErr: {err.append("this symbol not expected in " + name); break;}
		}
		err.append("\"; break;}\n");
	}

	private static int NewCondSet(BitSet s) {
		for (int i=1; i<=maxSS; i++) // skip symSet[0] (reserved for union of SYNC sets)
			if (s.equals(symSet[i])) return i;
		maxSS++; Tab.Assert(maxSS <= maxSymSets, 5);
		symSet[maxSS] = (BitSet) s.clone();
		return maxSS;
	}

	private static void GenCond(BitSet s) {
		int n, i;
		n = Sets.Size(s);
		if (n==0) gen.print("false"); // should never happen
		else if (n <= maxTerm)
			for (i=0; i<=Tab.maxT; i++) {
				if (s.get(i)) {
					gen.print("t.kind == "); PrintTermName(i);
					n--; if (n > 0) gen.print(" || ");
				}
			}
		else gen.print("StartOf(" + NewCondSet(s) + ")");
	}

	private static void PutCaseLabels(BitSet s) {
		int max = s.size();
		for (int i=0; i<=max; i++)
			if (s.get(i)) { 
				gen.print("case "); 
				PrintTermName(i);
				gen.print(": ");
			}
	}

	private static void GenCode (int p, int indent, BitSet checked) {
		GraphNode n, n2;
		BitSet s1, s2;
		boolean equal;
		int alts, p2;
		Symbol sym;
		while (p > 0) {
			n = Tab.Node(p);
			switch (n.typ) {
				case Tab.nt: {
					Indent(indent);
					sym = Tab.Sym(n.p1);
					if (n.retVar!=null) gen.print(n.retVar + " = ");
					gen.print(sym.name + "(");
					CopySourcePart(n.pos, 0);
					gen.println(");");
					break;
				}
				case Tab.t: {
					Indent(indent);
					if (checked.get(n.p1)) gen.println("Get();");
					else {
						gen.print("Expect("); PrintTermName(n.p1); gen.println(");");
					}
					break;
				}
				case Tab.wt: {
					Indent(indent);
					s1 = Tab.Expected(Math.abs(n.next), curSy);
					s1.or(Tab.Set(0));
					gen.print("ExpectWeak("); PrintTermName(n.p1); gen.println(", " + NewCondSet(s1) + ");");
					break;
				}
				case Tab.any: {
					Indent(indent);
					gen.println("Get();");
					break;
				}
				case Tab.eps: break; // nothing
				case Tab.sem: {
					CopySourcePart(n.pos, indent);
					break;
				}
				case Tab.sync: {
					Indent(indent);
					GenErrorMsg(syncErr, curSy);
					s1 = (BitSet) Tab.Set(n.p1).clone();
					gen.print("while (!("); GenCond(s1);
					gen.println(")) {Error(" + errorNr + "); Get();}");
					break;
				}
				case Tab.alt: {
					s1 = Tab.First(p); equal = s1.equals(checked);
					alts = Alternatives(p);
					if (alts > maxAlter) {Indent(indent); gen.println("switch (t.kind) {");}
					p2 = p;
					while (p2 != 0) {
						n2 = Tab.Node(p2);
						s1 = Tab.Expected(n2.p1, curSy);
						Indent(indent);
						if (alts > maxAlter) {PutCaseLabels(s1); gen.println("{");}
						else if (p2==p) {gen.print("if ("); GenCond(s1); gen.println(") {");}
						else if (n2.p2==0 && equal) gen.println("} else {");
						else {gen.print("} else if ("); GenCond(s1); gen.println(") {");}
						s1.or(checked);
						GenCode(n2.p1, indent + 1, s1);
						if (alts > maxAlter) {
							Indent(indent); gen.println("\tbreak;");
							Indent(indent); gen.println("}");
						}
						p2 = n2.p2;
					}
					Indent(indent);
					if (equal) gen.println("}");
					else {
						GenErrorMsg(altErr, curSy);
						if (alts > maxAlter) {
							gen.println("default: Error(" + errorNr + ");");
							Indent(indent); gen.println("}");
						} else
							gen.println("} else Error(" + errorNr + ");");
					}
					break;
				}
				case Tab.iter: {
					Indent(indent);
					n2 = Tab.Node(n.p1);
					gen.print("while (");
					if (n2.typ==Tab.wt) {
						s1 = Tab.Expected(Math.abs(n2.next), curSy);
						s2 = Tab.Expected(Math.abs(n.next), curSy);
						gen.print("WeakSeparator(");
						PrintTermName(n2.p1); gen.print(", " + NewCondSet(s1) + ", "
							+ NewCondSet(s2) + ")");
						s1 = new BitSet(); // for inner structure
						if (n2.next > 0) p2 = n2.next; else p2 = 0;
					} else {
						p2 = n.p1; s1 = Tab.First(p2); GenCond(s1);
					}
					gen.println(") {");
					GenCode(p2, indent + 1, s1);
					Indent(indent); gen.println("}");
					break;
				}
				case Tab.opt:
					s1 = Tab.First(n.p1);
					if (!checked.equals(s1)) {
						Indent(indent);
						gen.print("if ("); GenCond(s1); gen.println(") {");
						GenCode(n.p1, indent+1, s1);
						Indent(indent); gen.println("}");
					} else GenCode(n.p1, indent, checked);
					break;
			}
			if (n.typ!=Tab.eps && n.typ!=Tab.sem && n.typ!=Tab.sync) checked = new BitSet();
			p = n.next;
		}
	}

	private static void GenCodePragmas() {
		for (int i=Tab.maxT+1; i<=Tab.maxP; i++) {
			gen.println("\t\t\tif (t.kind == " + i + ") {");
			CopySourcePart(Tab.Sym(i).semPos, 4);
			gen.println("\t\t\t}");
		}
	}

	private static void GenProductions() {
		Symbol sym;
		for (curSy=Tab.firstNt; curSy<=Tab.lastNt; curSy++) {
			sym = Tab.Sym(curSy);
			gen.print("\tprivate static ");
			if (sym.retType==null) gen.print("void "); else gen.print(sym.retType + " ");
			gen.print(sym.name + "(");
			CopySourcePart(sym.attrPos, 0);
			gen.println(") {");
			if (sym.retVar!=null) gen.println("\t\t" + sym.retType + " " + sym.retVar + ";");
			CopySourcePart(sym.semPos, 2);
			GenCode(sym.struct, 2, new BitSet());
			if (sym.retVar!=null) gen.println("\t\treturn " + sym.retVar + ";");
			gen.println("\t}"); gen.println();
		}
	}

	private static void InitSets() {
		int i, j;
		BitSet s;
		symSet[0] = Tab.Set(0);
		for (i=0; i<=maxSS; i++) {
			gen.print("\t{"); s = symSet[i];
			for (j=0; j<=Tab.maxT; j++) {
				if (s.get(j)) gen.print("T,"); else gen.print("x,");
				if ((j+1) % 60 == 0) {gen.println(); gen.print("\t ");}
				else if (j%4==3) gen.print(" ");
			}
			if (i < maxSS) gen.println("x},"); else gen.println("x}");
		}
	}

	static String GetString(int beg, int end) {
		StringBuffer s = new StringBuffer();
		int oldPos = Buffer.pos;
		Buffer.Set(beg);
		while (beg < end) {s.append((char)Buffer.read()); beg++;}
		Buffer.Set(oldPos);
		return s.toString();
	}

	static void WriteParser(boolean withNames) {
		Symbol root = Tab.Sym(Tab.gramSy);

// Portability - Use the following for Java 1.0
//		try {fram = new BufferedInputStream(new FileInputStream("Parser.frame"));}

// Portability - Use the following for Java 1.1
//		try {fram = new BufferedReader(new FileReader("Parser.frame"));}

		try {fram = new BufferedReader(new FileReader("Parser.frame"));}

		catch (IOException e) {
			Scanner.err.Exception("-- cannot open Parser.frame. " +
			"Must be in application directory.");
		}
		try {

// Portability - Use the following for Java 1.0
//			gen = new PrintStream(new BufferedOutputStream(new FileOutputStream(srcDir + "Parser.java")));}
// Portability - Use the following for Java 1.1
//			gen = new PrintWriter(new BufferedWriter(new FileWriter(srcDir + "Parser.java")));}

			gen = new PrintWriter(new BufferedWriter(new FileWriter(srcDir + "Parser.java")));}

		catch (IOException e) {
			Scanner.err.Exception("-- cannot generate parser file");
		}
		if (withNames) Tab.AssignNames();
		err = new StringBuffer(2048);
		for (int i=0; i<=Tab.maxT; i++) GenErrorMsg(tErr, i);
		gen.println("package " + root.name + ";");
		CopyFramePart("-->constants");
		gen.println("\tprivate static final int maxT = " + Tab.maxT + ";");
		gen.println("\tprivate static final int maxP = " + Tab.maxP + ";");
		CopyFramePart("-->declarations"); CopySourcePart(Tab.semDeclPos, 0);
		CopyFramePart("-->pragmas"); GenCodePragmas();
		CopyFramePart("-->productions"); GenProductions();
		CopyFramePart("-->parseRoot"); gen.println("\t\t" + Tab.Sym(Tab.gramSy).name + "();");
		CopyFramePart("-->initialization"); InitSets();
		CopyFramePart("-->ErrorStream");
		gen.close();

		try {

// Portability - Use the following for Java 1.0
//			gen = new PrintStream(new BufferedOutputStream(new FileOutputStream(srcDir + "ErrorStream.java")));}
// Portability - Use the following for Java 1.1
//			gen = new PrintWriter(new BufferedWriter(new FileWriter(srcDir + "ErrorStream.java")));}

			gen = new PrintWriter(new BufferedWriter(new FileWriter(srcDir + "ErrorStream.java"))); }

		catch (IOException e) {
			Scanner.err.Exception("-- cannot generate error stream file");
		}
		gen.println("package " + root.name + ";");
		CopyFramePart("-->errors");
		String es = err.toString();
		for (int j = 0; j < es.length(); j++) { // PDT
			if (es.charAt(j)!='\n') gen.print(es.charAt(j)); else gen.println();
		}
		CopyFramePart("$$$");

		if (withNames) { // generate class of terminal names
			gen.println();
			gen.println("class SYM {");
			for (int n = 0; n < Tab.maxT; n++) {
				gen.println("\tstatic final int " + Tab.sy[n].symName + " = " + n + ";");
			}
			gen.println("}");
		}
		gen.close();
	}

	static void WriteStatistics() {
		Trace.println("Statistics:");
		Trace.println(Int(Tab.maxT+1, 4) + " terminals - Max " + Tab.maxTerminals);
		Trace.println(Int(Tab.lastNt - Tab.firstNt + 1, 4) + " non-terminals - Max " + (Tab.maxSymbols - Tab.maxT - 1));
		Trace.println(Int(Tab.maxSymbols - Tab.firstNt+Tab.maxT + 1, 4) + " symbols - Max " + Tab.maxSymbols);
		Trace.println(Int(Tab.nNodes, 4) + " graph nodes - Max " + Tab.maxNodes);
		Trace.println(Int(maxSS - 1, 4) + " symbol sets - Max " + maxSymSets);
		Trace.println(Int(Tab.maxC, 4) + " character sets - Max " + Tab.maxClasses);
		Trace.println();
	}

	static void Init(String dir) {
		srcDir = dir;
		errorNr = -1;
		symSet = new BitSet[maxSymSets];
		maxSS = 0; // symSet[0] reserved for union of all SYNC sets
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -