MNodePtr ans;
FTableVal* t;
MLFunc* u;
- ustring* name = cell->car ()->sym;
+ const ustring* name = ptr_symbol (cell->car ());
MNodePtr bcell;
MNode* sexp;
break;
case MNode::MC_STR:
return cell;
- case MNode::MC_SYM:
- if (cell->sym->length () > 0) {
- switch ((*cell->sym)[0]) {
+ case MNode::MC_SYM: {
+ const ustring* u = ptr_symbol (cell);
+ if (u->length () > 0) {
+ switch ((*u)[0]) {
case '#':
case ':':
return cell;
}
}
- return mlenv->getVar (*cell->sym);
+ return mlenv->getVar (*u);
+ }
case MNode::MC_DOUBLE:
return cell;
case MNode::MC_VECTOR:
-// return vectorEval (cell, mlenv);
-// return cell;
return vectorDup (cell);
case MNode::MC_TABLE:
-// return tableEval (cell, mlenv);
-// return cell;
return tableDup (cell);
default:
assert (0);
#ifdef DEBUG2
// std::cerr << "eval:" << to_string ((*b) ()) << "\n";
#endif /* DEBUG */
- x->tablePut ((*b).first, eval ((*b).second (), mlenv));
+ x->tablePut ((*b).first, eval ((*b).second (), mlenv)); // テーブルのキーは、文字列。
}
return ans.release ();
return ans;
}
-bool isLambda (MNode* sexp) {
- return (sexp && sexp->isCons () && sexp->car () && sexp->car ()->isSym () && (*sexp->car ()->sym) == uLambda);
-}
-
MNode* buildArgs (int start, const std::vector<ustring>& args) {
MNodeList ans;
MNode* sexp = lambda->cdr ();
MNode* param;
AutoDelete<KwList> kwlist;
- ustring* u;
+ const ustring* u;
ustring k;
bool skip;
for (param = sexp->car (); param; nextNode (param)) {
- u = param->car ()->sym;
+ u = ptr_symbol (param->car ());
if (match (*u, CharConst ("&rest"))) {
break;
} else if (match (*u, CharConst ("&key"))) {
for (param = sexp->car (); param;) {
u = NULL;
if (kwlist () && values && values->car ()->isSym ()
- && (u = values->car ()->sym)->length () > 0
+ && (u = ptr_symbol (values->car ()))->length () > 0
&& (*u)[0] == '#'
&& kwlist ()->defined (k = ustring (u->begin () + 1, u->end ()))) {
nextNode (values);
&& kwlist ()->defined (k = ustring (u->begin () + 1, u->end ()))) {
nextNode (values);
nextNode (values);
- } else if (match (*(u = param->car ()->sym), CharConst ("&rest"))) {
+ } else if (match (*(u = ptr_symbol (param->car ())), CharConst ("&rest"))) {
nextNode (param);
if (param) {
values = NULL;
for (; values;) {
u = NULL;
if (kwlist () && values && values->car ()->isSym ()
- && (u = values->car ()->sym)->length () > 0
+ && (u = ptr_symbol (values->car ()))->length () > 0
&& (*u)[0] == '#'
&& kwlist ()->defined (k = ustring (u->begin () + 1, u->end ()))) {
nextNode (values);
MNode* body = sexp->cdr ();
MNodePtr ans;
AutoDelete<KwList> kwlist;
- ustring* u;
+ const ustring* u;
ustring k;
bool skip;
MNode* values0 = values;
mlenv->beginLocal ();
// it is assumed that param is a list of symbols.
for (param = sexp->car (); param; nextNode (param)) {
- u = param->car ()->sym;
+ u = ptr_symbol (param->car ());
if (match (*u, CharConst ("&rest"))) {
break;
} else if (match (*u, CharConst ("&key"))) {
for (param = sexp->car (); param;) {
u = NULL;
if (kwlist () && values && values->car () && values->car ()->isSym ()
- && (u = values->car ()->sym)->length () > 0
+ && (u = ptr_symbol (values->car ()))->length () > 0
&& (*u)[0] == '#'
&& kwlist ()->defined (k = ustring (u->begin () + 1, u->end ()))) {
mlenv->setLocalVar (k, mlTrue);
else
mlenv->setLocalVar (k, NULL);
nextNode (values);
- } else if (match (*(u = param->car ()->sym), CharConst ("&rest"))) {
+ } else if (match (*(u = ptr_symbol (param->car ())), CharConst ("&rest"))) {
nextNode (param);
if (param) {
- mlenv->setLocalVar (*param->car ()->sym, values);
+ mlenv->setLocalVar (*ptr_symbol (param->car ()), values);
values = NULL;
} else {
throw (sexp->car ()->dump_string_short () + uErrorBadParamDef);
for (; values;) {
u = NULL;
if (kwlist () && values && values->car ()->isSym ()
- && (u = values->car ()->sym)->length () > 0
+ && (u = ptr_symbol (values->car ()))->length () > 0
&& (*u)[0] == '#'
&& kwlist ()->defined (k = ustring (u->begin () + 1, u->end ()))) {
mlenv->setLocalVar (k, mlTrue);
void setParams (MNode* list, int nparam, std::vector<MNode*>* params, paramList *kwlist, std::vector<MNode*>* keywords, MNode** rest, bool padding) {
KwList* kw = NULL;
- ustring* u;
+ const ustring* u;
MNode* a;
int i;
ustring name;
while (list) {
a = list->car ();
- if (a && kw && a->isSym () && (u = a->sym) && u->size () > 0) {
+ if (a && kw && a->isSym () && (u = ptr_symbol (a)) && u->size () > 0) {
switch ((*u)[0]) {
case ':':
name = ustring (u->begin () + 1, u->end ());
void progn_ex (MNode* arg, MlEnv* mlenv);
void checkDefun (MNode* cell, ustring& rname, MNode*& sexp);
MNode* newLambda (MNode* cell);
-bool isLambda (MNode* sexp);
MNode* buildArgs (int start, const std::vector<ustring>& args);
MNode* buildArgs (int start, const std::vector<ustring>& args, const ustring& arg2);
MNode* buildArgs (const ustring& arg1);
}
}
+ustring MNode::sym_to_string () {
+ assert (type == MC_SYM);
+ uiterator b = sym->begin ();
+ uiterator e = sym->end ();
+ umatch m;
+ if (b < e && usearch (b, e, m, re_nonsymbolchar)) {
+ ustring ans;
+ do {
+ ans.append (b, m[0].first).append (1, '\\').append (octchar (*m[0].first));
+ b = m[0].second;
+ } while (b < e && usearch (b, e, m, re_nonsymbolchar));
+ if (b < e)
+ ans.append (b, e);
+ return ans;
+ } else {
+ return *sym;
+ }
+}
+
ustring MNode::cons_to_texp (bool fcdr) {
// fcdr: cdr部の出力
ustring ans;
assert (type == MC_CONS);
if (! fcdr
-// && cons.car && cons.car->type == MC_SYM && cons.car->str->compare ("quote") == 0
&& cons.car && cons.car->type == MC_SYM && *cons.car->str == uQuote
&& cons.cdr && cons.cdr->type == MC_CONS
&& ::isNil (cons.cdr->cons.cdr)) {
case MNode::MC_STR:
return uQ2 + slashEncode (*str) + uQ2;
case MNode::MC_SYM:
- return *sym;
+ return sym_to_string ();
case MNode::MC_DOUBLE:
return to_ustring (real);
case MNode::MC_VECTOR:
case MNode::MC_STR:
return *str;
case MNode::MC_SYM:
- return *sym;
+ return *sym; // to-stringでは、エンコードしない
case MNode::MC_DOUBLE:
return to_ustring (real);
case MNode::MC_VECTOR:
return ans;
}
+MNode* quoted (MNode* v) {
+ if (v) {
+ switch (v->type) {
+ case MNode::MC_SYM:
+ if (v->sym
+ && v->sym->length () > 0
+ && ((*v->sym)[0] == '#' || (*v->sym)[0] == ':')) {
+ } else {
+ v = newMNode_quote (v);
+ }
+ break;
+ case MNode::MC_CONS:
+ v = newMNode_quote (v);
+ break;
+ default:;
+ }
+ }
+ return v;
+}
+
+MNode* newMNode_sym (ustring* v) {
+ static uregex re_special ("[\\x00-\x1f\\\\]");
+ static uregex re_oct ("^[0-7][0-7][0-7]");
+ MNode* ans = new MNode;
+ uiterator b = v->begin ();
+ uiterator e = v->end ();
+ umatch m;
+
+ if (b < e && usearch (b, e, m, re_special)) {
+ ustring* w = new ustring;
+ do {
+ w->append (b, m[0].first);
+ b = m[0].second;
+ if (*(m[0].first) == '\\') {
+ if (b < e && usearch (b, e, m, re_oct)) {
+ int c = octchar (b);
+ if (32 <= c && c < 127)
+ w->append (1, c);
+ b = m[0].second;
+ } else {
+ w->append (1, '\\');
+ }
+ } else {
+ // skip;
+ }
+ } while (b < e && usearch (b, e, m, re_special));
+ if (b < e)
+ w->append (b, e);
+ ans->set_sym (w);
+ delete v;
+ } else {
+ ans->set_sym (v);
+ }
+ return ans;
+}
+
void MNode::dump (std::ostream& o, bool c) {
o << logText (to_texp ());
}
void MotorTexp::scanWord (int& linenum, uiterator& b, uiterator& e, word_type& type, ustring*& ans) {
ustring::value_type c;
umatch m;
- static uregex re ("^[^\\x00- ()\\[\\]\\{\\}\";]+");
- static uregex re_num ("[\\-+]?[0-9]+(\\.[0-9]*)?");
Ep1:;
skipWhite (linenum, b, e);
if (b != e) {
c = *b;
switch (c) {
+ case '\"':
+ b ++;
+ type = YYTEXT;
+ ans = scanText (linenum, b, e);
+ break;
+ case '\'':
+ b ++;
+ type = YYQUOTE;
+ ans = NULL;
+ break;
case '(':
b ++;
type = YYPAR;
b ++;
type = YYREN;
break;
+ case ';':
+ b ++;
+ if (usearch (b, e, m, re_nl)) {
+ b = m[0].second;
+ linenum ++;
+ goto Ep1;
+ } else {
+ // end of comment but without nl.
+ b = e;
+ type = YYNONE;
+ }
+ break;
case '[':
b ++;
type = YYPAR2;
b ++;
type = YYREN3;
break;
- case '\"':
- b ++;
- type = YYTEXT;
- ans = scanText (linenum, b, e);
- break;
- case ';':
- b ++;
- if (usearch (b, e, m, re_nl)) {
- b = m[0].second;
- linenum ++;
- goto Ep1;
- } else {
- // end of comment but without nl.
- b = e;
- type = YYNONE;
- }
- break;
default:
- if (usearch (b, e, m, re)) {
+ if (usearch (b, e, m, re_realnumber)) {
+ type = YYNUM;
+ ans = new ustring (m[0]);
+ b = m[0].second;
+ } else if (usearch (b, e, m, re_symbol)) {
assert (b == m[0].first);
- if (*b == '\'') {
- b ++;
- type = YYQUOTE;
- ans = NULL;
- } else if (*b == '.' && m[0].second - m[0].first == 1) {
+ if (*b == '.' && m[0].second - m[0].first == 1) {
type = YYPERIOD;
b = m[0].second;
} else {
- umatch m2;
- if (regex_match (m[0].first, m[0].second, m2, re_num)) {
- type = YYNUM;
- ans = new ustring (m[0]);
- b = m[0].second;
- } else {
- type = YYSIM;
- ans = new ustring (m[0]);
- b = m[0].second;
- }
+ type = YYSIM;
+ ans = new ustring (m[0]);
+ b = m[0].second;
}
skipWhite (linenum, b, e);
} else {
return (int64_t)to_double ();
};
bool to_bool ();
+ ustring sym_to_string ();
ustring cons_to_texp (bool fcdr = false);
ustring to_texp ();
ustring to_string ();
return (a != NULL && a->isTable ());
}
+inline bool isLambda (MNode* sexp) {
+ return (sexp && sexp->isCons () && sexp->car () && sexp->car ()->isSym () && (*sexp->car ()->sym) == uLambda);
+}
+
+inline const ustring* ptr_symbol (MNode* e) {
+ assert (isSym (e));
+ return e->sym;
+}
+
class MNodePtr;
ustring formatString (const ustring& format, boost::ptr_vector<MNodePtr>& par);
bool eq (MNode* a, MNode* b);
}
#define dump_to_sexp(x) dump_to_texp(x)
-inline MNode* newMNode_sym (ustring* v) {
- MNode* ans = new MNode;
- ans->set_sym (v);
- return ans;
-}
+MNode* quoted (MNode* v);
+MNode* newMNode_sym (ustring* v);
inline MNode* newMNode_str (ustring* v) {
MNode* ans = new MNode;
}
inline MNode* newMNode_symQuote () {
-// return newMNode_sym (new ustring (CharConst ("quote")));
return newMNode_sym (new ustring (uQuote));
}
for (i = 0; i < mlPool->includeCount; i ++)
*log << ":";
logLinenum (c);
-// *log << c->dump_string_short () << "\n";
if (c->car () && c->car ()->isSym ()
- && (match (*c->car ()->sym, CharConst ("defun")) || matchHead (*c->car ()->sym, CharConst ("defun-")))
+ && (match (*ptr_symbol (c->car ()), CharConst ("defun")) || matchHead (*ptr_symbol (c->car ()), CharConst ("defun-")))
&& c->cdr () && c->cdr ()->isCons ()
&& c->cdr ()->cdr () && c->cdr ()->cdr ()->isCons ()) {
*log << "(" << c->car ()->dump_string ();
if (! s5 (sobjs, start)) {
return 0; // NG
}
- } else if (usearch (name.first, name.second, m, re_num)) {// [[NUM:
+ } else if (usearch (name.first, name.second, m, re_digits)) {// [[NUM:
AutoDelete<MotorObjTempl> o;
uiterator b = begin;
}
bool checkNum (const uiterator& b, const uiterator& e) {
- return (checkRe (b, e, re_num));
+ return (checkRe (b, e, re_digits));
}
bool checkWidth (const uiterator& b, const uiterator& e) {
bool checkMimeType (const ustring& name);
bool checkMailAddr (const ustring& name);
bool checkAlNum (const uiterator& b, const uiterator& e);
-bool checkNum (const ustring& text);
+bool checkNum (const ustring& text); // [0-9]+
bool checkNum (const uiterator& b, const uiterator& e);
bool checkWidth (const uiterator& b, const uiterator& e);
bool checkWidth (const ustring& text);
uregex re_comma (",");
//uregex re_amp ("&");
//uregex re_eq ("=");
-uregex re_num ("^[0-9]+$");
+uregex re_digits ("^[0-9]+$");
+uregex re_realnumber ("^[+-]?[0-9]+(\\.[0-9]*)?([eE][+-]?[0-9]+)?");
+uregex re_symbol ("^[^\\x00- \"'();\\[\\]\\{\\}]+");
+uregex re_nonsymbolchar ("[\\x00- \"'();\\[\\]\\{\\}\\\\]"); // \を含める
uregex re_q ("\"");
MNode* mlTrue = NULL;
extern uregex re_comma;
//extern uregex re_amp;
//extern uregex re_eq;
-extern uregex re_num;
+extern uregex re_digits;
+extern uregex re_realnumber;
+extern uregex re_symbol;
+extern uregex re_nonsymbolchar;
extern uregex re_q;
extern MNode* mlTrue;
}
return ans;
}
+
+int octchar (uiterator b) { // 3bytes
+ int ans = 0;
+ ans = *b - '0';
+ ++ b;
+ ans = ans * 8 + *b - '0';
+ ++ b;
+ ans = ans * 8 + *b - '0';
+ return ans;
+}
+
+ustring octchar (int c) {
+ ustring ans (3, 0);
+ ans[2] = (c & 0x7) + '0';
+ c >>= 3;
+ ans[1] = (c & 0x7) + '0';
+ c >>= 3;
+ ans[0] = (c & 0x3) + '0';
+ return ans;
+}
ustring toLower (const ustring& str);
ustring toUpper (const ustring& str);
ustring hexEncode (const ustring& data);
+int octchar (uiterator b);
+ustring octchar (int c);
#endif /* UTIL_STRING_H */
} else {
return NULL;
}
-// return newMNode_str (new ustring (text));
}
/*DOC:
#include "ustring.h"
#include <exception>
-static MNode* symquote (MNode* v) {
- if (v) {
- switch (v->type) {
- case MNode::MC_SYM:
- if (v->sym
- && v->sym->length () > 0
- && ((*v->sym)[0] == '#' || (*v->sym)[0] == ':')) {
- } else {
- v = newMNode_quote (v);
- }
- break;
- case MNode::MC_CONS:
- v = newMNode_quote (v);
- break;
- default:;
- }
- }
- return v;
-}
-
/*DOC:
==lisp structure==
} else if (fn ()->isSym ()) {
while (arg) {
if (! isNil (arg->cdr ())) {
- list.append (symquote (eval (arg->car (), mlenv)));
+ list.append (quoted (eval (arg->car (), mlenv)));
} else {
MNode* a;
h = eval (arg->car (), mlenv);
a = h ();
while (a && a->isCons ()) {
- list.append (symquote (a->car ()));
+ list.append (quoted (a->car ()));
nextNode (a);
}
}
MotorVar::iterator b = e ()->table->begin ();
MotorVar::iterator t = e ()->table->end ();
for (; b != t; ++ b) {
- ans.append (newMNode_cons (newMNode_sym (new ustring ((*b).first)), (*b).second ()));
+ ans.append (newMNode_cons (newMNode_str (new ustring ((*b).first)), (*b).second ())); // テーブルのキーは、シンボルではなく文字列
}
return ans.release ();
MotorVar::iterator b = tbl ()->table->begin ();
MotorVar::iterator t = tbl ()->table->end ();
for (; b != t; ++ b) {
- mlenv->setVar (vkey, newMNode_sym (new ustring ((*b).first)));
+ mlenv->setVar (vkey, newMNode_str (new ustring ((*b).first))); // テーブルのキーは、文字列
mlenv->setVar (vval, (*b).second ());
ans = progn (rest, mlenv);
if (mlenv->breaksym ()) {
}
}
-static void setLocalVar (ustring& name, MNode* val, MlEnv* mlenv) {
- if (checkAry (name, name)) {
- mlenv->defineLocalVar (name);
- mlenv->setAry (name, val);
+static void setLocalVar (const ustring& name, MNode* val, MlEnv* mlenv) {
+ ustring aname;
+ if (checkAry (name, aname)) {
+ mlenv->defineLocalVar (aname);
+ mlenv->setAry (aname, val);
} else {
mlenv->setLocalVar (name, val);
}
if (varlist && varlist->isCons ()) {
MNode* v;
MNodePtr p;
- ustring* name;
+ const ustring* name;
while (varlist) {
v = varlist->car ();
switch (v->type) {
case MNode::MC_CONS:
if (v->car ()->isSym ()) {
- name = v->car ()->sym;
+ name = ptr_symbol (v->car ());
nextNode (v);
p = eval (v->car (), mlenv);
setLocalVar (*name, p (), mlenv);
}
break;
case MNode::MC_SYM:
- name = v->sym;
+ name = ptr_symbol (v);
mlenv->setLocalVar (*name, NULL);
break;
default:
/*DOC:
===wiki-output===
- (wiki-output TEXT... [#flush | :flush BOOL]) -> NIL
+ (wiki-output [#flush | :flush BOOL] TEXT...) -> NIL
*/
//#AFUNC wiki-output ml_wiki_output
ustring text;
MNode* a;
ustring* u;
+ bool b;
+ std::vector<MNode*> keywords;
+ MNode* rest;
+ static paramList kwlist[] = {
+ {CharConst ("flush"), true},
+ {NULL, 0, 0}
+ };
- while (arg) {
- a = arg->car ();
- if (a && a->isSym ()) {
- u = a->sym;
- if (match ((*u), CharConst (":flush"))) {
- nextNodeNonNil (arg);
- if (eval_bool (arg->car (), mlenv)) {
- if (mlenv->env->wikioutput)
- mlenv->env->wikioutput->flush (true);
- }
- nextNode (arg);
- } else if (match ((*u), CharConst ("#flush"))) {
- nextNode (arg);
- if (mlenv->env->wikioutput)
- mlenv->env->wikioutput->flush (true);
- } else {
- if (mlenv->env->wikioutput)
- mlenv->env->wikioutput->out_toText (eval_str (arg->car (), mlenv));
- nextNode (arg);
- }
- } else {
- if (mlenv->env->wikioutput)
- mlenv->env->wikioutput->out_toText (eval_str (arg->car (), mlenv));
- nextNode (arg);
- }
+ setParams (arg, 0, NULL, kwlist, &keywords, &rest);
+ if (evkw_bool (0, b))
+ if (mlenv->env->wikioutput)
+ mlenv->env->wikioutput->flush (true);
+
+ while (rest) {
+ if (mlenv->env->wikioutput)
+ mlenv->env->wikioutput->out_toText (eval_str (rest->car (), mlenv));
+ nextNode (rest);
}
return NULL;
virtual ~XmlReaderData_txml () {};
virtual void newNode (const XML_Char* name, const XML_Char** atts) {
-// MNode* a = newMNode_vector ();
MNodeList a;
-// a->vectorPush (newMNode_sym (new ustring (fixUTF8 (ustring (name)))));
a.append (newMNode_sym (new ustring (fixUTF8 (ustring (name)))));
a.append (NULL);
if (atts && *atts) {
MNode* c = newMNode_table ();
-// a->vectorPush (c);
a.append (c);
for (; *atts; ) {
c->tablePut (fixUTF8 (ustring (*atts ++)), newMNode_str (new ustring (fixUTF8 (ustring (*atts ++)))));
}
}
-// ptr.push_back (a);
ptr.push_back (a.release ());
mode.push_back (M_START);
text.resize (0);
case M_START:
break;
case M_TEXT:
-// a->vectorPush (newMNode_str (new ustring (text)));
a->cdr ()->set_car (newMNode_str (new ustring (text)));
break;
case M_CHILD:
if (ptr.size () == 0) {
ans = a;
} else {
-// ptr.back ()->vectorPush (a);
MNode* b = ptr.back ()->cdr ();
MNode* c = b->car ();
if (! c) {
if (isCons (list) && isSym (list->car ())) {
MNode* c;
MNode* d;
- ustring* name = list->car ()->sym;
+ const ustring* name = ptr_symbol (list->car ());
list = list->cdr ();
if (isCons (list)) {
out->out_raw (CharConst ("<"))->out_toHTML_noCtrl (*name);
MNode* c;
MNode* d;
MNode* e;
- ustring* name = list->car ()->sym;
+ const ustring* name = ptr_symbol (list->car ());
list = list->cdr ();
out->out_raw (CharConst ("<"))->out_toHTML_noCtrl (*name);
if (isCons (list) && isCons (c = list->car ())
- && isSym (d = c->car ()) && *d->sym == uAt) { // attribute
+ && isSym (d = c->car ()) && *ptr_symbol (d) == uAt) { // attribute
c = c->cdr ();
list = list->cdr ();
while (isCons (c)) {
MNode* c;
MNode* d;
if (isCons (list) && isSym (c = list->car ())) {
- ustring* name = c->sym;
+ const ustring* name = ptr_symbol (c);
list = list->cdr ();
out->out_raw (CharConst ("<"))->out_toHTML_noCtrl (*name);
if (isCons (list)) {