开始看 Lua 源码也有段时间了,由于尝试用各种方式切入,效果均不是很理想,应该是个人内功不做所致。加上先阶段个人时间有限,现记录下断点,待到来日能力足够有兴趣时再来看。
初期探索:
0、由于第一次尝试读源码,开始时竟将源码按大小顺序排列,从小文件看起。
1、尝试从数据结构看起,看完了 Lua 的数据结构后对 Lua 的数据结构还是有种朦胧的感觉。然后尝试看 Lua 的 GC 终止。
2、尝试把 Lua 当作一个程序来看,从 main 函数开始读,函数调用层层深入下去。。。作为一个菜鸟,这注定是失败的尝试。
3、从网络中找各种源码分析的文章看,源码分析看看看去也就几块,有一个人分析过了后就有一批人跟着转载,不够系统,不能随心。
4、看到了云风的 Lua 源码欣赏中关于源码的阅读顺序的合理方式,觉得可行,又一次尝试。
试读准备:
1、个人机器为 Win7 使用的源码编译工具为 minGW ,minGW 下载链接:http://sourceforge.net/projects/mingw/?source=typ_redirect。
可以使用 mingw32-make Makefile 编译 Lua 源码(说明:个人用的 Lua 源码为 5.1.4 编译出来的 dll 文件 163 kb, 然后总觉得 luaforWindows 里的 dll 要好些,就索性把 luaforWindows 的目录下的 include 文件夹和 lib 文件夹下的文件拷贝出来放在测试文件夹下不要自己编译的了)。
2、编写简单批处理生成动态链接库(make.bat)。
@echo off
set curdir=%~dp0
pushd %curdir%
set CFN=%1
REM remove the last build
(del /q %CFN%.dll) 2>nul
REM get file name except extension
if "%CFN:~-2%" == ".c" set CFN=%CFN:~0,-2%
gcc -shared -o %CFN%.dll %CFN%.c -B %curdir% -llua5.1
popd
echo on
View Code
3、提取源码测试(LuaStr.c)。
/*
Time :2015-04-07 09:13:23
Function :Lua 的正则匹配试读 ( 截取自 Lua 源码 )
Creater :Lazy_Pupa
*/
/*
输出说明 :_Fun_i_Step_k : Output Message -- i:功能代号, k:第几步。
1: str_find_aux; 2: posrelat; 3: match; 4: start_capture; 5: end_capture;
6: capture_to_close; 7: matchbalance; 8: classend; 9: matchbracketclass;
10: match_capture; 11: singlematch; 12: max_expand; 13: min_expand; 14: push_captures;
15: push_onecapture; 16: match_class; 17: check_capture; 18: ; 19: ; 20: ;
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#define uchar(c) ((unsigned char)(c))
#define CAP_UNFINISHED (-1)
#define CAP_POSITION (-2)
#define L_ESC '%'
#define SPECIALS "^$*+?.([%-"
int Step = 0;
typedef struct MatchState{
const char *str_init;
const char *str_end;
lua_State *L;
int level;
struct {
const char *init;
ptrdiff_t len;
}capture[LUA_MAXCAPTURES];
}MatchState;
/*
function: calculate relate position
parameters: (pos, len)
return: (-4, 2) -> 0; (-3, 2) -> 0; (-2, 2) -> 1; (-1, 2) -> 2;
(0, 2) -> 0; (1, 2) -> 1; (2, 2) -> 2; (3, 2) -> 3;
*/
static ptrdiff_t posrelat(ptrdiff_t pos, size_t len) {
printf("_Fun_%02d_Step_%3d : parameters %d, %d\n", 2, ++Step, pos, len);
if(pos < 0) pos += (ptrdiff_t)len + 1;
printf("_Fun_%02d_Step_%3d :return %d ? %d : 0\n", 2, ++Step, (pos >= 0), pos);
return (pos >= 0) ? pos : 0;
}
static const char *classend(MatchState *ms, const char *p) { // find the %f[match] pattern ']'
// ms: 查找状态; *p: 匹配字符串
printf("_Fun_%02d_Step_%3d : parameters '%s'\n", 8, ++Step, p);
switch(*p++){
case L_ESC:{
if (*p == '\0')
luaL_error(ms->L, "malformed pattern (end with " LUA_QL("%%") ")");
printf("_Fun_%02d_Step_%3d :case L_ESC return '%s'\n", 8, ++Step, p + 1);
return p + 1;
}
case '[':{
if(*p == '^') p++;
do{
if(*p == '\0')
luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
if(*(p++) == L_ESC && *p != '\0')
p++;
}while(*p != ']');
printf("_Fun_%02d_Step_%3d :case '[' return '%s'\n", 8, ++Step, p + 1);
return p + 1;
}
default:{
printf("_Fun_%02d_Step_%3d :default return '%s'\n", 8, ++Step, p);
return p;
}
}
}
static int match_class(int c, int cl) {
printf("_Fun_%02d_Step_%3d : parameters %d, %d\n", 16, ++Step, c, cl);
int res;
switch (tolower(cl)){
case 'a': res = isalpha(c); break;
case 'c': res = iscntrl(c); break;
case 'd': res = isdigit(c); break;
case 'l': res = islower(c); break;
case 'p': res = ispunct(c); break;
case 's': res = isspace(c); break;
case 'u': res = isupper(c); break;
case 'w': res = isalnum(c); break;
case 'x': res = isxdigit(c); break;
case 'z': res = (c == 0); break;
default: return (cl == c);
}
printf("_Fun_%02d_Step_%3d :return (%d ? %d : %d)\n", 16, ++Step, islower(cl), res, !res);
return (islower(cl) ? res : !res);
}
static int matchbracketclass(int c, const char *p, const char *ec) { // 匹配模版类。
// c: ; *p: 匹配字符串; *ec: 匹配结束位置。
printf("_Fun_%02d_Step_%3d : parameters %c, '%s', '%s'\n", 9, ++Step, c, p, ec);
int sig = 1;
if (*(p+1) == '^') {
sig = 0;
p++;
}
while (++p < ec) {
if (*p == L_ESC) {
p++;
if (match_class(c, uchar(*p)))
{
printf("_Fun_%02d_Step_%3d :if return %d\n", 9, ++Step, sig);
return sig;
}
}
else if ((*(p+1) == '-') && (p+2 < ec)) {
p += 2;
if (uchar(*(p-2)) <= c && c <= uchar(*p))
{
printf("_Fun_%02d_Step_%3d :else if return %d\n", 9, ++Step, sig);
return sig;
}
}
else if (uchar(*p) == c)
{
printf("_Fun_%02d_Step_%3d :else if 2 return %d\n", 9, ++Step, sig);
return sig;
}
}
printf("_Fun_%02d_Step_%3d :return %d\n", 9, ++Step, !sig);
return !sig;
}
static int singlematch(int c, const char *p, const char *ep) {
// c: source char; *p: pattern string; *ep: pattern end
printf("_Fun_%02d_Step_%3d : parameters %d, '%s', '%s'\n", 11, ++Step, c, p, ep);
switch(*p){
case '.':
printf("_Fun_%02d_Step_%3d :return 1;\n", 11, ++Step);
return 1;
case L_ESC:
printf("_Fun_%02d_Step_%3d :return match_class(c, uchar(*(p+1)));\n", 11, ++Step);
return match_class(c, uchar(*(p+1)));
case '[':
printf("_Fun_%02d_Step_%3d :return matchbracketclass(c, p, ep-1);\n", 11, ++Step);
return matchbracketclass(c, p, ep-1);
default:
printf("_Fun_%02d_Step_%3d :default return %d\n", 11, ++Step, (uchar(*p) == c));
return (uchar(*p) == c);
}
}
static const char *match(MatchState *ms, const char *s, const char *p);
static const char *matchbalance(MatchState *ms, const char *s, const char *p) {
// ms: 查找状态; *s: 源字符串; *p: 匹配字符串
// printf("ms->str_end = '%s', *s = '%s', *p = '%s'\n", ms->str_end, s, p);
printf("_Fun_%02d_Step_%3d : parameters '%s', '%s'\n", 7, ++Step, s, p);
if(*p == 0 || *(p+1) == 0) // *p 以 %b"结尾。
luaL_error(ms->L, "unbalanced pattern");
if (*s != *p)
{
printf("_Fun_%02d_Step_%3d :if return NULL\n", 7, ++Step);
return NULL;
}
else {
int b = *p; // 开始
int e = *(p+1); // 结束
int cont = 1; //
while (++s < ms->str_end) {
// printf("*s = %d, b = %d, e = %d, cont = %d\n*s = '%s'\n", *s, b, e, cont, s);
if (*s == e) {
if (--cont == 0)
{
printf("_Fun_%02d_Step_%3d :return '%s'\n", 7, ++Step, s+1);
return s+1;
}
}else if (*s == b) cont++; // 支持嵌套
}
}
printf("_Fun_%02d_Step_%3d :return NULL\n", 7, ++Step);
return NULL;
}
static const char *max_expand(MatchState *ms, const char *s, const char *p, const char *ep) {
// ms: 查找状态; *s: 源字符串; *p: 匹配字符串; *ep: 匹配字符串结尾
printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', '%s'\n", 12, ++Step, s, p, ep);
ptrdiff_t i = 0;
while((s+i) < ms->str_end && singlematch(uchar(*(s+i)), p, ep)) // anchor the match tail
i++;
while (i >= 0) {
const char *res = match(ms, (s+i), ep+1); //
if (res)
{
printf("_Fun_%02d_Step_%3d :return '%s'\n", 12, ++Step, res);
return res;
}
i--;
}
printf("_Fun_%02d_Step_%3d :return NULL\n", 12, ++Step);
return NULL;
}
static const char *min_expand(MatchState *ms, const char *s, const char *p, const char *ep) {
printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', '%s'\n", 13, ++Step, s, p, ep);
for(;;) {
const char *res = match(ms, s, ep+1);
if (res != NULL)
{
printf("_Fun_%02d_Step_%3d : return '%s'\n", 13, ++Step, res);
return res;
}
else if (s<ms->str_end && singlematch(uchar(*s), p, ep))
s++;
else
{
printf("_Fun_%02d_Step_%3d : return NULL\n", 13, ++Step);
return NULL;
}
}
}
static const char *start_capture(MatchState *ms, const char *s, const char *p, int what) {
// ms: 查找状态; *s: 源字符串; *p: 匹配字符串; what: 标记捕获是否结束
printf("_Fun_%02d_Step_%3d : parameters %d, '%s', '%s', %d\n", 4, ++Step, ms->level, s, p, what);
const char *res;
int level = ms->level; // 捕获个数
if (level > LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
ms->capture[level].init = s;
ms->capture[level].len = what; // 捕获状态
ms->level = level + 1; // 捕获加一。
if ((res=match(ms, s, p)) == NULL)
ms->level--;
printf("_Fun_%02d_Step_%3d :return '%s'\n", 4, ++Step, res);
return res;
}
// 嵌套捕获结束 如:src = "Lua Test String!"; matchString = "((%a+) %a+)"; return "Lua Test", "Lua";
static int capture_to_close(MatchState *ms) {
// ms: 查找状态
printf("_Fun_%02d_Step_%3d : parameters %d\n", 6, ++Step, ms->level);
int level = ms->level; // 查找深度
for(level--; level>=0; level--) // 查找该捕获的起始深度
if(ms->capture[level].len == CAP_UNFINISHED)
{
printf("_Fun_%02d_Step_%3d :return %d\n", 6, ++Step, level);
return level;
}
printf("_Fun_%02d_Step_%3d :return error\n", 6, ++Step);
return luaL_error(ms->L, "invalid pattern capture");
}
static const char *end_capture(MatchState *ms, const char *s, const char *p) {
// ms: 查找状态; *s: 源字符串; *p: 捕获之后的字符串
printf("_Fun_%02d_Step_%3d : parameters '%s', '%s'\n", 5, ++Step, s, p);
int l = capture_to_close(ms); // 匹配的左括号。
printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', '%s', %d\n", 5, ++Step, ms->capture[l].init, s, p, s - ms->capture[l].init);
const char *res;
ms->capture[l].len = s - ms->capture[l].init; // 记录捕获长度。
if((res = match(ms, s, p)) == NULL) // 捕获结束,开始后续匹配。
ms->capture[l].len = CAP_UNFINISHED; // UNKNOW... Um, just mark capture unfinished.
printf("_Fun_%02d_Step_%3d :return '%s'\n", 5, ++Step, res);
return res;
}
static int check_capture(MatchState *ms, int l) {
// ms : 查找状态; l : 匹配字符。
printf("_Fun_%02d_Step_%3d : parameters %d, %d, %d\n", 17, ++Step, ms->level, ms->capture[l].len, l);
l -= '1';
if (l<0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
return luaL_error(ms->L, "invalid capture index");
printf("_Fun_%02d_Step_%3d : parameters %d\n", 17, ++Step, l);
return l;
}
static const char *match_capture(MatchState *ms, const char *s, int l) {
// ms : 查找状态; *s : 查找源字符串; l : 匹配字符。
printf("_Fun_%02d_Step_%3d : parameters '%s', %d\n", 10, ++Step, s, l);
size_t len;
l = check_capture(ms, l);
printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', %d\n", 10, ++Step, ms->capture[l].init, s, l);
len = ms->capture[l].len;
printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', %d, %d\n", 10, ++Step, ms->capture[l].init, s, l, s+len);
if ((size_t)(s+len) >= len && memcmp(ms->capture[l].init, s, len) == 0)
{
printf("_Fun_%02d_Step_%3d :return '%s'\n", 10, ++Step, s+len);
return s+len;
}
else
{
printf("_Fun_%02d_Step_%3d :return NULL\n", 10, ++Step);
return NULL;
}
}
static const char *match(MatchState *ms, const char *s, const char *p) {
// ms : 查找状态; *s : 查找源字符串; *p : 匹配字符串。
init:
printf("_Fun_%02d_Step_%3d : parameters *ms, '%s', '%s'\n", 3, ++Step, s, p);
switch(*p) {
case '(':{
if (*(p+1) == ')') // 空捕获返回捕获的起始位置。如 find('Lua', '()') -> 1, 0, 1; find('Lua', '%a()') -> 1, 1, 2;
{
printf("_Fun_%02d_Step_%3d :return start_capture(ms, s, p+2, CAP_POSITION)\n", 3, ++Step);
return start_capture(ms, s, p+2, CAP_POSITION);
}
else
{
printf("_Fun_%02d_Step_%3d :return start_capture(ms, s, p+1, CAP_UNFINISHED)\n", 3, ++Step);
return start_capture(ms, s, p+1, CAP_UNFINISHED);
}
}
case ')':{
printf("_Fun_%02d_Step_%3d :return end_capture(ms, s, p+1)\n", 3, ++Step);
return end_capture(ms, s, p+1);
}
case L_ESC:{ // translate meaning char
switch(*(p+1)) {
case 'b':{
s = matchbalance(ms, s, p+2); //
if (s == NULL)
{
printf("_Fun_%02d_Step_%3d :case 'b' return NULL\n", 3, ++Step);
return NULL;
}
p += 4;
printf("_Fun_%02d_Step_%3d :case 'b' goto init\n", 3, ++Step);
goto init;
}
case 'f':{ // {LuaStr.find("Lua Test String!", "(%f[%a+])") -> 1 0} 没懂这是干嘛的。。。。
const char *ep;
char previous;
p += 2;
if (*p != '[')
luaL_error(ms->L, "missing" LUA_QL("[") " after " LUA_QL("%%f") " in pattern");
ep = classend(ms, p); // anchor the %f[] end.
previous = (s == ms->str_init) ? '\0' : *(s-1);
if (matchbracketclass(uchar(previous), p, ep-1) || !matchbracketclass(uchar(*s), p, ep-1))
{
printf("_Fun_%02d_Step_%3d :case 'f' return NULL\n", 3, ++Step);
return NULL;
}
p = ep;
printf("_Fun_%02d_Step_%3d :case 'f' goto init\n", 3, ++Step);
goto init;
}
default: {
if (isdigit(uchar(*(p+1)))) {
s = match_capture(ms, s, uchar(*(p+1))); // 源自符指针后移,至下一个匹配开始。
if (s == NULL)
{
printf("_Fun_%02d_Step_%3d :case L_ESC return NULL\n", 3, ++Step);
return NULL;
}
p += 2;
printf("_Fun_%02d_Step_%3d :default goto init\n", 3, ++Step);
goto init;
}
printf("_Fun_%02d_Step_%3d :case L_ESC goto dflt\n", 3, ++Step);
goto dflt;
}
}
}
case '\0':{
printf("_Fun_%02d_Step_%3d :case '\\0' return '%s'\n", 3, ++Step, s);
return s;
}
case '$':{
if (*(p+1) == '\0') // 是否匹配结束位置。
{
printf("_Fun_%02d_Step_%3d :case '$' return %d ? s : NULL\n", 3, ++Step, (s == ms->str_end));
return (s == ms->str_end) ? s : NULL;
}
else
{
printf("_Fun_%02d_Step_%3d :case '\0' goto dflt\n", 3, ++Step);
goto dflt;
}
}
default: dflt: {
const char *ep = classend(ms, p); // check single match, if true jump to '[match string]' end ,( ep: end of *p)
int m = s<ms->str_end && singlematch(uchar(*s), p, ep); // 简单匹配标识。
switch(*ep) {
case '?':{ // 匹配 0 次或 1 次。
const char *res;
if (m && ((res = match(ms, s+1, ep+1)) != NULL)) // UNKNOW ... Um, like match a result.
{
printf("_Fun_%02d_Step_%3d :case '?' return '%s'\n", 3, ++Step, res);
return res;
}
p=ep+1; // Don't match any result.
printf("_Fun_%02d_Step_%3d :case '?' goto init\n", 3, ++Step);
goto init;
}
case '*':{ // 匹配 0 次或多次。
printf("_Fun_%02d_Step_%3d :return max_expand(ms, s, p, ep)\n", 3, ++Step);
return max_expand(ms, s, p, ep);
}
case '+':{ // 匹配 1 次或多次。
printf("_Fun_%02d_Step_%3d :return (m ? max_expand(ms, s+1, p, ep) : NULL)\n", 3, ++Step);
return (m ? max_expand(ms, s+1, p, ep) : NULL);
}
case '-':{ // 匹配 0 次或多次。
printf("_Fun_%02d_Step_%3d :return min_expand(ms, s, p, ep)\n", 3, ++Step);
return min_expand(ms, s, p, ep);
}
default: {
if (!m)
{
printf("_Fun_%02d_Step_%3d :default: dflt: return NULL\n", 3, ++Step);
return NULL;
}
s++;
p=ep;
printf("_Fun_%02d_Step_%3d :default: dflt goto init\n", 3, ++Step);
goto init;
}
}
}
}
}
static const char * lmemfind(const char *s1, size_t l1, const char *s2, size_t l2) {
return NULL;
}
static void push_onecapture(MatchState *ms, int i, const char *s, const char *e) {
printf("_Fun_%02d_Step_%3d : parameters %d, '%s', '%s'\n", 15, ++Step, i, s, e);
if (i>=ms->level) {
if (i == 0)
lua_pushlstring(ms->L, s, e - s);
else
luaL_error(ms->L, "invalid capture index!");
}
else {
ptrdiff_t l = ms->capture[i].len;
if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
if (l == CAP_POSITION)
lua_pushinteger(ms->L, ms->capture[i].init - ms->str_init +1);
else
lua_pushlstring(ms->L, ms->capture[i].init, l);
}
}
static int push_captures(MatchState *ms, const char *s, const char *e) {
printf("_Fun_%02d_Step_%3d : parameters %d, '%s', '%s'\n", 14, ++Step, ms->level, s, e);
int i;
int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
luaL_checkstack(ms->L, nlevels, "too many captures");
for(i=0; i<nlevels; i++)
push_onecapture(ms, i, s, e);
printf("_Fun_%02d_Step_%3d :return %d\n", 14, ++Step, nlevels);
return nlevels;
}
static int str_find_aux(lua_State *L, int find) {
printf("_Fun_%02d_Step_%3d : parameters find = %d\n", 1, ++Step, find);
size_t srcStrLen, matchStrLen;
const char *srcStr = luaL_checklstring(L, 1, &srcStrLen);
const char *matchStr = luaL_checklstring(L, 2, &matchStrLen);
ptrdiff_t startFindPostion = posrelat(luaL_optinteger(L, 3, 1), srcStrLen) - 1;
if(startFindPostion < 0) startFindPostion = 0;
else if ((size_t)(startFindPostion) > srcStrLen) startFindPostion = (ptrdiff_t)srcStrLen;
if (find && (lua_toboolean(L, 4) || strpbrk(matchStr, SPECIALS) == NULL)) {
const char *s2 = lmemfind(srcStr+startFindPostion, srcStrLen-startFindPostion, matchStr, matchStrLen); // 常规匹配查找
if (s2) {
lua_pushinteger(L, s2-srcStr+1);
lua_pushinteger(L, s2-srcStr+matchStrLen);
printf("_Fun_%02d_Step_%3d :return 2.\n", 1, ++Step);
return 2;
}
}
else { // 正则匹配查找
MatchState ms;
int anchor = (*matchStr == '^') ? (matchStr++, 1) : 0; // 是否定位头部
const char *s1 = srcStr + startFindPostion; // 待查找的字符串
ms.L = L; // 保存脚本上下文
ms.str_init = srcStr; // 保存待查找的字符串
ms.str_end = srcStr + srcStrLen; // 保存字符串结束位置
do {
const char *res;
ms.level = 0; // 设置默认捕获的数量
if ((res=match(&ms, s1, matchStr)) != NULL) { // 匹配主体部分
if (find) { // 返回查找结果
lua_pushinteger(L, s1-srcStr+1);
lua_pushinteger(L, res-srcStr);
printf("_Fun_%02d_Step_%3d :return push_captures(&ms, NULL, 0) + 2\n", 1, ++Step);
return push_captures(&ms, NULL, 0) + 2;
}else // 返回匹配结果
{
printf("_Fun_%02d_Step_%3d :return push_captures(&ms, s1, res)\n", 1, ++Step);
return push_captures(&ms, s1, res);
}
}
}while (s1++ < ms.str_end && !anchor); // 一次匹配不成功且非从头部开始定位则继续。
}
lua_pushnil(L); // 查找失败。
printf("_Fun_%02d_Step_%3d :return 1.\n", 1, ++Step);
return 1;
}
static int str_find(lua_State *L) {
printf(
"=================================== Lua Find Test ===================================\n"
" 1: str_find_aux ; 4: start_capture ; 5: end_capture; 2: posrelat; 3: match;\n"
" 6: capture_to_close; 7: matchbalance ; 8: classend ; 9: matchbracketclass;\n"
"10: match_capture ; 11: singlematch ; 12: max_expand ; 13: min_expand;\n"
"14: push_captures ; 15: push_onecapture; 16: match_class; 17: check_capture;\n"
"=================================== Lua Find Test ===================================\n");
return str_find_aux(L, 1);
}
static const luaL_Reg strlib[] = {
{"find", str_find},
{NULL, NULL}
};
// Open String Library
extern int luaopen_LuaStr(lua_State *L) {
const char *libraryName = "LuaStr";
luaL_register(L, libraryName, strlib);
return 1;
}
View Code
4、编译测试代码 make LuaStr.c
5、测试源码
require "LuaStr"
print(LuaStr.find("Lua Test String!", "(%f[%a+])"));
6、运行看结果
=================================== Lua Find Test ===================================
1: str_find_aux ; 4: start_capture ; 5: end_capture; 2: posrelat; 3: match;
6: capture_to_close; 7: matchbalance ; 8: classend ; 9: matchbracketclass;
10: match_capture ; 11: singlematch ; 12: max_expand ; 13: min_expand;
14: push_captures ; 15: push_onecapture; 16: match_class; 17: check_capture;
=================================== Lua Find Test ===================================
_Fun_01_Step_ 1 : parameters find = 1
_Fun_02_Step_ 2 : parameters 1, 16
_Fun_02_Step_ 3 :return 1 ? 1 : 0
_Fun_03_Step_ 4 : parameters *ms, 'Lua Test String!', '(%f[%a+])'
_Fun_03_Step_ 5 :return start_capture(ms, s, p+1, CAP_UNFINISHED)
_Fun_04_Step_ 6 : parameters 0, 'Lua Test String!', '%f[%a+])', -1
_Fun_03_Step_ 7 : parameters *ms, 'Lua Test String!', '%f[%a+])'
_Fun_08_Step_ 8 : parameters '[%a+])'
_Fun_08_Step_ 9 :case '[' return ')'
_Fun_09_Step_ 10 : parameters , '[%a+])', '])'
_Fun_16_Step_ 11 : parameters 0, 97
_Fun_16_Step_ 12 :return (2 ? 0 : 1)
_Fun_09_Step_ 13 :return 0
_Fun_09_Step_ 14 : parameters L, '[%a+])', '])'
_Fun_16_Step_ 15 : parameters 76, 97
_Fun_16_Step_ 16 :return (2 ? 1 : 0)
_Fun_09_Step_ 17 :if return 1
_Fun_03_Step_ 18 :case 'f' goto init
_Fun_03_Step_ 19 : parameters *ms, 'Lua Test String!', ')'
_Fun_03_Step_ 20 :return end_capture(ms, s, p+1)
_Fun_05_Step_ 21 : parameters 'Lua Test String!', ''
_Fun_06_Step_ 22 : parameters 1
_Fun_06_Step_ 23 :return 0
_Fun_05_Step_ 24 : parameters 'Lua Test String!', 'Lua Test String!', '', 0
_Fun_03_Step_ 25 : parameters *ms, 'Lua Test String!', ''
_Fun_03_Step_ 26 :case '\0' return 'Lua Test String!'
_Fun_05_Step_ 27 :return 'Lua Test String!'
_Fun_04_Step_ 28 :return 'Lua Test String!'
_Fun_01_Step_ 29 :return push_captures(&ms, NULL, 0) + 2
_Fun_14_Step_ 30 : parameters 1, '(null)', '(null)'
_Fun_15_Step_ 31 : parameters 0, '(null)', '(null)'
_Fun_14_Step_ 32 :return 1
1 0
View Code
另外,需要 Lua 用户手册, 网址:http://www.lua.org/manual/5.1/