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