PageRenderTime 35ms CodeModel.GetById 24ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/extra/webapps/fjsc/www/termlib/termlib_parser.js

http://github.com/abeaumont/factor
JavaScript | 199 lines | 170 code | 2 blank | 27 comment | 0 complexity | 6338d73f73979c689f9b77da83eb6b32 MD5 | raw file
  1/*
  2  termlib_parser.js  v.1.0
  3  command line parser for termlib.js
  4  (c) Norbert Landsteiner 2005
  5  mass:werk - media environments
  6  <http://www.masswerk.at>
  7
  8  you are free to use this parser under the "termlib.js" license.
  9
 10  usage:  call "parseLine(this)" from your Terminal handler
 11          parsed args in this.argv
 12          quoting levels per arg in this.argQL (value: quote char)
 13          this.argc: pointer to this.argv and this.argQL (used by parserGetopt)
 14          call parseretopt(this, "<options>") from your handler to get opts
 15          (returns an object with properties for every option flag. any float
 16          values are stored in Object.<flag>.value; illegal opts in array
 17          Object.illegals)
 18
 19  configuration: you may want to overide the follow objects (or add properties):
 20          parserWhiteSpace: chars to be parsed as whitespace
 21          parserQuoteChars: chars to be parsed as quotes
 22          parserSingleEscapes: chars to escape a quote or escape expression
 23          parserOptionChars: chars that start an option
 24          parserEscapeExpressions: chars that start escape expressions
 25*/
 26
 27// chars to be parsed as white space
 28var parserWhiteSpace = {
 29	' ': true,
 30	'\t': true
 31}
 32
 33// chars to be parsed as quotes
 34var parserQuoteChars = {
 35	'"': true,
 36	"'": true,
 37	'`': true
 38};
 39
 40// chars to be parsed as escape char
 41var parserSingleEscapes = {
 42	'\\': true
 43};
 44
 45// chars that mark the start of an option-expression
 46// for use with parserGetopt
 47var parserOptionChars = {
 48	'-': true
 49}
 50
 51// chars that start escape expressions (value = handler)
 52// plugin handlers for ascii escapes or variable substitution
 53var parserEscapeExpressions = {
 54	'%': parserHexExpression
 55}
 56
 57function parserHexExpression(termref, pointer, echar, quotelevel) {
 58	/* example for parserEscapeExpressions
 59	   params:
 60	     termref: ref to Terminal instance
 61	     pointer: position in termref.lineBuffer (echar)
 62	     echar:   escape character found
 63	     quotelevel: current quoting level (quote char or empty)
 64	   char under pointer will be ignored
 65	   the return value is added to the current argument
 66	*/
 67	// convert hex values to chars (e.g. %20 => <SPACE>)
 68	if (termref.lineBuffer.length > pointer+2) {
 69		// get next 2 chars
 70		var hi = termref.lineBuffer.charAt(pointer+1);
 71		var lo = termref.lineBuffer.charAt(pointer+2);
 72		lo = lo.toUpperCase();
 73		hi = hi.toUpperCase();
 74		// check for valid hex digits
 75		if ((((hi>='0') && (hi<='9')) || ((hi>='A') && ((hi<='F')))) &&
 76		    (((lo>='0') && (lo<='9')) || ((lo>='A') && ((lo<='F'))))) {
 77			// next 2 chars are valid hex, so strip them from lineBuffer
 78			parserEscExprStrip(termref, pointer+1, pointer+3);
 79			// and return the char
 80			return String.fromCharCode(parseInt(hi+lo, 16));
 81		}
 82	}
 83	// if not handled return the escape character (=> no conversion)
 84	return echar;
 85}
 86
 87function parserEscExprStrip(termref, from, to) {
 88	// strip characters from termref.lineBuffer (for use with escape expressions)
 89	termref.lineBuffer =
 90		termref.lineBuffer.substring(0, from) +
 91		termref.lineBuffer.substring(to);
 92}
 93
 94function parserGetopt(termref, optsstring) {
 95    // scans argv form current position of argc for opts
 96    // arguments in argv must not be quoted
 97	// returns an object with a property for every option flag found
 98	// option values (absolute floats) are stored in Object.<opt>.value (default -1)
 99	// the property "illegals" contains an array of  all flags found but not in optstring
100	// argc is set to first argument that is not an option
101	var opts = { 'illegals':[] };
102	while ((termref.argc < termref.argv.length) && (termref.argQL[termref.argc]==''))  {
103		var a = termref.argv[termref.argc];
104		if ((a.length>0) && (parserOptionChars[a.charAt(0)])) {
105			var i = 1;
106			while (i<a.length) {
107				var c=a.charAt(i);
108				var v = '';
109				while (i<a.length-1) {
110					var nc=a.charAt(i+1);
111					if ((nc=='.') || ((nc>='0') && (nc<='9'))) {
112						v += nc;
113						i++;
114					}
115					else break;
116				}
117				if (optsstring.indexOf(c)>=0) {
118					opts[c] = (v == '')? {value:-1} : (isNaN(v))? {value:0} : {value:parseFloat(v)};
119				}
120				else {
121					opts.illegals[opts.illegals.length]=c;
122				}
123				i++;
124			}
125			termref.argc++;
126		}
127		else break;
128	}
129	return opts;
130}
131
132function parseLine(termref) {
133	// stand-alone parser, takes a Terminal instance as argument
134	// parses the command line and stores results as instance properties
135	//   argv:  list of parsed arguments
136	//   argQL: argument's quoting level (<empty> or quote character)
137	//   argc:  cursur for argv, set initinally to zero (0)
138	// open quote strings are not an error but automatically closed.
139	var argv = [''];     // arguments vector
140	var argQL = [''];    // quoting level
141	var argc = 0;        // arguments cursor
142	var escape = false ; // escape flag
143	for (var i=0; i<termref.lineBuffer.length; i++) {
144		var ch= termref.lineBuffer.charAt(i);
145		if (escape) {
146			argv[argc] += ch;
147			escape = false;
148		}
149		else if (parserEscapeExpressions[ch]) {
150			var v = parserEscapeExpressions[ch](termref, i, ch, argQL[argc]);
151			if (typeof v != 'undefined') argv[argc] += v;
152		}
153		else if (parserQuoteChars[ch]) {
154			if (argQL[argc]) {
155				if (argQL[argc] == ch) {
156					argc ++;
157					argv[argc] = argQL[argc] = '';
158				}
159				else {
160					argv[argc] += ch;
161				}
162			}
163			else {
164				if (argv[argc] != '') {
165					argc ++;
166					argv[argc] = '';
167					argQL[argc] = ch;
168				}
169				else {
170					argQL[argc] = ch;
171				}
172			}
173		}
174		else if (parserWhiteSpace[ch]) {
175			if (argQL[argc]) {
176				argv[argc] += ch;
177			}
178			else if (argv[argc] != '') {
179				argc++;
180				argv[argc] = argQL[argc] = '';
181			}
182		}
183		else if (parserSingleEscapes[ch]) {
184			escape = true;
185		}
186		else {
187			argv[argc] += ch;
188		}
189	}
190	if ((argv[argc] == '') && (!argQL[argc])) {
191		argv.length--;
192		argQL.length--;
193	}
194	termref.argv = argv;
195	termref.argQL = argQL;
196	termref.argc = 0;
197}
198
199// eof