📄 parse.java
字号:
/* Copyright 2004-2006 David N. Welton Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */package org.hecl;import java.util.Enumeration;import java.util.Vector;/** * The <code>Parse</code> class takes care of parsing Hecl scripts. * * @author <a href="mailto:davidw@dedasys.com">David N. Welton </a> * @version 1.0 */public class Parse { /* Used to build up commands. */ protected Vector outList; protected ParseState state; protected Interp interp = null; protected String in; /* Used to build up individual Things with. */ protected StringThing outBuf; protected boolean outBufNumeric = true; protected boolean outBufused = false; /* Used to build up words (that might be GroupThings). */ protected Vector outGroup; protected boolean parselist = false;//#ifdef j2se protected static final char eol[] = System.getProperty("line.separator").toCharArray();//#else protected static final char eol[] = { '\n' };//#endif /** * The <code>more</code> method returns a boolean value indicating whether * there is more text to be parsed or not. * * @return a <code>boolean</code> value */ public boolean more() { return !state.eof; } /** * Creates a new <code>Parse</code> instance. Not actually used by * anything. * */ public Parse() { } /** * Creates a new <code>Parse</code> instance. * * @param interp_in * a <code>Interp</code> value * @param in_in * a <code>String</code> value */ public Parse(Interp interp_in, String in_in) { interp = interp_in; in = in_in; state = new ParseState(in); } /** * The <code>parse</code> method runs the parser on the text added by * creating a new Parse instance. * * @return a <code>Vector</code> value * @exception HeclException if an error occurs */ public Vector parse() throws HeclException { outList = new Vector(); newCurrent(); state.eoc = false; parseLine(state); if (outList.size() > 0) { //System.out.println("outlist is : " + outList); return outList; } return null; } /** * <code>parseToCode</code> parses up a [] section as code. * * @return a <code>CodeThing</code> value * @exception HeclException if an error occurs */ public CodeThing parseToCode() throws HeclException { CodeThing code = new CodeThing(); int i = 0; Vector cmd; Thing[] argv; int cmdsize = 0; int beginline = 0; while (more()) { beginline = state.lineno; cmd = parse(); // System.out.println("CMD is " + cmd + " lineno is " + beginline); if (cmd == null) { continue; } cmdsize = cmd.size(); if (cmdsize == 0) { continue; } argv = new Thing[cmdsize]; for (i = 0; i < cmdsize; i++) { argv[i] = (Thing) cmd.elementAt(i); } code.addStanza(interp, argv, beginline); } return code; } /** * The <code>newCurrent</code> method creates a new 'context' to * be added to. * * @exception HeclException if an error occurs */ protected void newCurrent() throws HeclException { outGroup = new Vector(); outBufused = false; } /** * The <code>addCurrent</code> method adds a new element to the command * parsed. * */ protected void addCurrent() throws HeclException { /* If it's only got one element, don't make a groupthing out * of it. */ if (outGroup.size() == 1) { /* Optimization - if it's composed entirely of numbers, * make an IntThing out of it. */ RealThing str = (RealThing)outGroup.elementAt(0); Thing newthing = null; if (outBufNumeric) { String s = str.getStringRep(); try { newthing = new Thing(NumberThing.asNumber(new Thing(s))); newthing.literal = true; } catch (NumberFormatException e) { } } if (newthing == null) { newthing = new Thing(str); newthing.literal = true; } outList.addElement(newthing); } else if (outGroup.size() > 1) { Vector outv = new Vector(); for (Enumeration e = outGroup.elements(); e.hasMoreElements();) { RealThing rt = (RealThing)e.nextElement(); outv.addElement(new Thing(rt).setLiteral()); } outList.addElement(GroupThing.create(outv).setLiteral()); } else { /* If nothing has been added (for example {}), then make * it an empty element. */ outList.addElement(new Thing("").setLiteral()); } newCurrent(); } /** * The <code>appendToCurrent</code> method adds a character to the group * object. * * @param ch a <code>char</code> */ protected void appendToCurrent(char ch) throws HeclException { if (!outBufused) { outBuf = new StringThing(); outBufNumeric = true; outBufused = true; outGroup.addElement(outBuf); } if (outBufNumeric && !Character.isDigit(ch) && ch != '.') { outBufNumeric = false; } outBuf.append(ch); } /* Used internally. */ private static final int DOLLAR = 0; private static final int COMMAND = 1; /** * The <code>addCommand</code> method adds a command to the current * output. * * @exception HeclException if an error occurs */ protected void addCommand() throws HeclException { addSub(COMMAND); } /** * The <code>addDollar</code> method adds a $var lookup to the current * output. * * @exception HeclException if an error occurs */ public void addDollar() throws HeclException { addSub(DOLLAR); } public void addSub(int type) throws HeclException { Vector savegroup = outGroup; StringThing savebuf = outBuf; newCurrent(); if (type == DOLLAR) { parseDollar(state); } else { parseCommand(state); } for (Enumeration e = outGroup.elements(); e.hasMoreElements();) { RealThing rt = (RealThing)e.nextElement(); savegroup.addElement(rt); } outBufused = false; outGroup = savegroup; } /** * The <code>parseLine</code> method is where parsing starts on a new * line. * * @param state a <code>ParseState</code> value * @exception HeclException if an error occurs */ public void parseLine(ParseState state) throws HeclException { char ch; while (true) { ch = state.nextchar(); if (state.done()) { return; } switch (ch) { case '\r' : return; case '\n' : state.lineno ++; return; case ';' : return; case ' ' : case ' ' : continue; case '{' : parseBlock(state); break; case '[' : parseCommand(state); break; case '$' : /* variables might be the start of the rest of a * word - for instance: ${foo}bar - so we parse * them as such. */ state.rewind(); parseWord(state); break; case '"' : parseText(state); break; case '\\' : if (!parseEscape(state)) { parseWord(state); break; } continue; case '#' : if (outList.size() == 0) { parseComment(state); return; } /* Fall through if it's not at the beginning of the line. */ default : appendToCurrent(ch);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -