我可以让宏像 \numexpr 一样运行吗?

我可以让宏像 \numexpr 一样运行吗?

例如我\fpeval在 Plain LuaTeX 中定义:

\begingroup
\catcode`\%=12
\directlua{
   function math.round_int ( x )
     return x>=0 and math.floor(x+0.5) or math.ceil(x-0.5)
   end
   function math.round ( x , n )
     return math.round_int ( x*10^n ) / 10^n 
   end
   function gobblezero(x)
     local y = math.round ( x , 8 )
     if y == math.floor(y) then
       return string.format ( "%.0f", y )
     else
       return math.round(y, 7)
     end
   end}
\endgroup

\def\fpeval#1{\directlua{tex.print(gobblezero(#1))}}

\directlua{%
    p = 68
    P = 80}

You have \fpeval{p} of \fpeval{P} points, this makes $\fpeval{p * 100/P}\,\%$.

\bye

但我想要一个名为的宏,\fpexpr其行为类似于\numexpr,以便我可以写道:

You have \fpexpr p of \fpexpr P points, this makes $\fpexpr p * 100/P \,\%$.

第一种情况\fpexpr应该只接受p作为参数,因为of从来没有被定义为数字或函数\directlua{of = ...}。第二种和第三种情况类似,因为points\,Lua 解释器中未定义。

因此\fpexpr应该将所有内容添加到 lua 代码中,直到添加的内容导致错误。

这可能吗?

答案1

在此处输入图片描述

这还远远未完成,但确实存在一些情况。

终端上的内容很丰富:

token is p
variable found 68 p
token is of
stop at of collected: 68
2: eval result is 68 x
token is P
variable found 80 P
token is points,
stop at points, collected: 80
2: eval result is 80 x
token is p
variable found 68 p
token is *
token is 100
token is /
token is P
variable found 80 P
token is ?
1: eval result is 85.0

代码是

\begingroup
\catcode`\%=12
\directlua{
   function math.round_int ( x )
     return x>=0 and math.floor(x+0.5) or math.ceil(x-0.5)
   end
   function math.round ( x , n )
     return math.round_int ( x*10^n ) / 10^n 
   end
   function gobblezero(x)
     local y = math.round ( x , 8 )
     if y == math.floor(y) then
       return string.format ( "%.0f", y )
     else
       return math.round(y, 7)
     end
   end}
\endgroup

\def\fpeval#1{\directlua{tex.print(gobblezero(#1))}}

{\catcode`\%=12
\xdef\pc{%}
}

\directlua{
function zz (s)
local t = token.scan_string()
print ('token is ' .. (t or '?'))
if (t == nil) then
local f = loadstring('r= ' .. s)
f()
print('1: eval result is ' .. (r or '?'))
tex.print(r)
else
% t is local variable or operator or number (inexact pattern)
if (_G[t] \string~= nil) then
% recurse with value
print ('variable found ' .. _G[t] .. ' ' .. t)
 zz(s .. _G[t])
else if(string.find(t,'^[+-/*().]?\pc d*$')) then
% recurse
 zz(s .. t)
else
% evaluate string so far and retrun result and the rejected token
print('stop at ' .. t ..  ' collected: ' .. s)
local f = loadstring('r= ' .. s)
f()
print('2: eval result is ' .. (r or '?') .. ' x')
tex.print(r .. ' ' .. t )
end
end
end
end
}

\def\fpzz{\directlua{zz('')}}

\directlua{%
    p = 68
    P = 80}

You have \fpzz p of \fpzz P points, this makes $\fpzz p * 100 / P \,\%$.

\bye

相关内容