File "AddProgramLine.java"
Path: /WAF - Wireless Android Framework/WAF_0.1_Android/src/rfo/mougino/waf/AddProgramLine.java
File size: 9.15 KB
MIME-type: text/plain
Charset: utf-8
/****************************************************************************************************
BASIC! is an implementation of the Basic programming language for
Android devices.
Copyright (C) 2010 - 2014 Paul Laughton
This file is part of BASIC! for Android
BASIC! is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
BASIC! is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with BASIC!. If not, see <http://www.gnu.org/licenses/>.
You may contact the author or current maintainers at http://rfobasic.freeforums.org
Contains contributions from Michael Camacho. 2012
*************************************************************************************************/
package rfo.mougino.waf;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import android.util.Log;
public class AddProgramLine {
private static final String LOGTAG = "AddProgramLine";
private static String kw_include = "include";
Boolean BlockFlag = false;
String stemp = "";
public static ArrayList<Integer> lineCharCounts;
public static int charCount = 0;
public AddProgramLine() {
charCount = 0; // Character count = 0
lineCharCounts = new ArrayList<Integer>(); // create a new list of line char counts
lineCharCounts.add(0); // First line starts with a zero char count
Basic.lines = new ArrayList<String>();
}
public void AddLine(String line) {
/* Adds one line to Basic.lines
* Each line will have all white space characters removed and all characters
* converted to lower case (unless they are within quotes).
*/
if (line == null) { return; }
// Look for block comments. All lines between block comments
// are tossed out
if (BlockFlag) {
if (line.startsWith("!!")) {
BlockFlag = false;
}
return;
}
if (line.startsWith("!!")) {
BlockFlag = true;
return;
}
String Temp = "";
int linelen = line.length();
for (int i=0; i < linelen; ++i) { // do not mess with characters
char c = line.charAt(i); // between quote marks
if (c == '"' || c == '\u201c') { // Change funny quote to real quote
StringBuilder sb = new StringBuilder();
i = doQuotedString(line, i, linelen, sb);
Temp += sb.toString();
} else if (c == '%') { // if the % character appears,
break; // drop it and the rest of the line
} else if (c == '~') { // Pre-processor: check for line continuation '~'
int j = i; // scan after character, skipping spaces and tabs
do { ++j; } while ((j < linelen) && (" \t".indexOf(line.charAt(j)) >= 0));
if ((j >= linelen) || (line.charAt(j) == '%')) { // EOL or comment
Temp += "{+nl}"; // add line continuation marker
break;
}
} else if (c != ' ' && c != '\t') { // toss out spaces and tabs
c = Character.toLowerCase(c); // normal character: convert to lower case
Temp += c; // and add it to the line
}
}
if (Temp.startsWith(kw_include)) { // If include,
doInclude(Temp); // Do the include
return;
}
if (Temp.startsWith("rem")) { Temp = ""; } // toss out REM lines
if (Temp.startsWith("!")) { Temp = ""; } // and whole-line comments
if (Temp.startsWith("%")) { Temp = ""; } // and end-of-line comments
if (!Temp.equals("")) { // and empty lines
if (stemp.length() == 0) { // whole line, or first line of a collection
// connected with continuation markers
lineCharCounts.add(charCount); // add char count to array of char counts
}
if (Temp.endsWith("{+nl}")) { // Pre-processor: test for include next line sequence
Temp = Temp.substring(0, Temp.length() - 5); // remove the include next line sequence
stemp = (stemp.length() == 0) ? Temp : mergeLines(stemp, Temp); // and collect the line
return;
} else if (stemp.length() > 0) {
Temp = mergeLines(stemp, Temp); // add stemp collection to line
stemp = ""; // clear the collection
}
Temp = shorthand(Temp); // Pre-processor: expand C/Java-like operators
if (Temp.contains("{")) { // Pre-processor: out any hidden substrings
Temp = Temp.replace("{+&=}", "+=");
Temp = Temp.replace("{-&=}", "-=");
Temp = Temp.replace("{*&=}", "*=");
Temp = Temp.replace("{/&=}", "/=");
}
Temp = Temp + "\n"; // end the line with New Line
Basic.lines.add(Temp); // add to Basic.lines
}
}
private int doQuotedString(String line, int index, int linelen, StringBuilder s) {
char c, c2;
s.append('"'); // Incoming index points at a quote
while (true) { // Loop until quote or no more characters
++index;
if (index >= linelen) { break; } // No more characters, done
else { c = line.charAt(index); } // next character
if (c == '"' || c == '\u201c') { // Found quote, done
break;
}
c2 = ((index + 1) < linelen) ? line.charAt(index + 1) : '\0';
if (c == '\\') {
if (c2 == '"' || c2 == '\\') { // look for \" or \\ and retain it
s.append('\\').append(c2); // so that user can have quotes and backslashes in strings
++index;
} else if (c2 == 'n') { // change backslash-n to carriage return
s.append('\r');
++index;
} else if (c2 == 't') { // change backslash-t to tab
s.append('\t');
++index;
} // else remove the backslash
} else if ( (c2 == '=') && // Pre-processor:
("+-*/".indexOf(c) >= 0) ) {// if +=, -=, *=, /= in string
s.append('{').append(c) // hide them temporarily
.append("&=}"); // by converting to "{+&=}", etc.
++index;
} else { s.append(c); } // not quote, backslash, or pre-processor operator
}
s.append('"'); // Close string. If no closing quote in user string, add one.
// If funny quote, convert it to ASCII quote.
return index; // leave index pointing at quote or EOL
}
private String mergeLines(String base, String addition) {
if (base.length() == 0) { return addition; }
if (addition.length() == 0) { return base; }
String specialCommands[] = { "array.load", "list.add" };
for (int i = 0; i < specialCommands.length; ++i) {
if ( base.startsWith(specialCommands[i]) && // command allows continuable data
(base.length() > specialCommands[i].length()) && // the command is not alone on the line
scanForComma(base) ) { // the command's first parameter is already present
char lastChar = base.charAt(base.length() - 1);
char nextChar = addition.charAt(0);
if (lastChar != ',' && nextChar != ',') { // no comma between adjacent parameters
base += ','; // insert comma between parameters
}
break;
}
}
return base + addition;
}
// return true iff line has a comma that is not in balanced parentheses or quotes
private boolean scanForComma(String line) {
boolean isQuote = false;
int parens = 0;
int brackets = 0;
int len = line.length();
char prevc = '\0';
for (int i = 0; i < len; ++i) {
char c = line.charAt(i);
switch (c) {
case '(': ++parens; break;
case ')': --parens; break;
case '[': ++brackets; break;
case ']': --brackets; break;
case '\"':
if (prevc != '\\') { isQuote = !isQuote; }
break;
case ',':
if (parens == 0 && brackets == 0 && !isQuote) { return true; }
}
prevc = c;
}
return false;
}
private String shorthand(String line) { // Pre-processor: expand C/Java-like operators
int ll = line.length();
int then = line.indexOf("then");
if (then == -1) {
if (line.startsWith("++") || line.startsWith("--")) {
line = line.substring(2, ll) + "=1" + line.substring(1, ll);
}
if (line.endsWith("++") || line.endsWith("--")) {
line = line.substring(0, ll - 2) + "=" + line.substring(0, ll - 1) + "1";
}
int tt = line.indexOf("+=");
if (tt < 0) {
tt = line.indexOf("-=");
if (tt < 0) {
tt = line.indexOf("*=");
if (tt < 0) {
tt = line.indexOf("/=");
}
}
}
if (tt > 0) {
line = line.substring(0, tt) + "=" + line.substring(0, tt + 1) + "(" + line.substring(tt + 2, ll) + ")";
}
return line;
}
then += 4;
String tline = line.substring(0, then);
line = line.substring(then, ll);
line = shorthand(line);
return tline + line;
}
private void doInclude(String fileName) {
fileName = fileName.substring(kw_include.length()).trim();
BufferedReader buf = null;
try { buf = Basic.getBufferedReader(Basic.SOURCE_DIR, fileName); }
catch (Exception e) {} // stream already closed if exception
if (buf == null) {
String t = "Error_Include_file (" + fileName + ") not_found";
AddLine(t);
return;
}
String data = null;
do {
try { data = buf.readLine(); }
catch (IOException e) { data = null; }
AddLine(data); // add the line
} while (data != null); // while not EOF and no error
}
}