greaterpn1>n2>
leqpn1<=n2<=
geqpn1>=n2>=
equalg1==g2==
nequalg1!
=g2!
=
bandx1&x2&
bnandx1~&x2~&
bxorx1^x2^
bxnorx1~^x2~^
borx1|x2|
bnorx1~|x2~|
andx1&&x2&&
orx1||x2||
rangeg1:
g2:
setqs=expr=
对于既有函数名又有操作符函数,采用函数名调用和采用操作符调用的效果是一样的。
示例lessp(31)=>nil等同于3<1=>nil
预定义算术函数
语法结果
通用函数
add1(n)n+1
sub1(n)n–1
abs(n)绝对值
exp(n)自然对数的n次方
log(n)
max(n1n2...)
min(n1n2...)
mod(x1x2)取模运算
round(n)
sqrt(n)
sxtd(xw)将x右扩展W个符号位
zxtd(xw)和上面的功能相同,速度更快
三角函数
sin(n),cos(n),tan(n)
asin(n),acos(n),atan(n)
随机数生成函数
random(x)产生0~x-1的随机数
srandom(x)初始化随机数生成函数的x
位操作
含义操作符
位与&
位或|
位异或^
左移位>>
右移位<<
取反~
真值、假值
▪真值,除了nil以为的值都是真值。
▪假值,nil
条件控制函数
if,when,unless,cond
▪if
if函数的语法结构
if(condition1then;当condition1为真值时执行代码块expA
expA
else
if(condition2then;当condition2为真值时执行代码块expB
expB
else
…
expC
)
);endif
▪when
when函数语法结构
when(condition;当condition为真值时执行代码块expA,否则跳过
expA
);endwhen
▪unless
unless语法结构
unless(condition;当condition为假值时执行代码块expA,否则跳过
expA
);endunless
▪cond
cond语法结构
cond(
(condition1expA...);当condition1为真值时执行代码块expA
(condition2expB...);…
(condition3expC...);…
(texpN);之前的条件都不满足时默认执行expN
);endcond
[注]:
";"表示注释
循环控制函数
while,for,foreach
▪while
while语法结构
while(conditionistrue;当condition为真值时反复执行代码块expA,否则结束循环
expA
)
▪for
for语法结构
for(i15
println(i)
)
将输出
1
2
3
4
5
▪foreach
foreach是简化版的for,上面的例子用foreach写如下
alist=‘(12345)
foreach(itemalist
println(item)
)
foreach通常用于操作列表,因为它会遍历列表的每一个元素。
选择函数
▪caseq的用法类似cond,功能也类似。
caseq(var
(condition1expA)
(condition2expB)
…
);case语法结构
循环结构中的局部变量
使用关键字prog可以在循环结构中定义局部变量。
关于prog的详细介绍请参考函数章节。
返回函数
表示返回值的关键字是return。
return可以强制一个prog结构立即结束,送出返回值,忽略剩余的循环操作。
示例prog(()
for(i010
when(oddp(i)
return(i)
);when
);for
);prog
这个for循环不会运行10次,首次oddp(i)为真值的时候循环就会结束。
正则表达式
在很多的skill应用中都会用到正则表达式,比如在一个字符串数组中查找带有关键字user的字符串。
示例:
lStr='("hello""whenuser""usercome""ffuser""ppuserd""uster");
lRes=nil
foreach(itemlStr
if(rexMatchp("user"item)then
lRes=cons(itemlRes)
println(item)
)
)
输出:
"whenuser""usercome""ppuserd"
lRes=>("ppuserd""usercome""whenuser").
这里的关键命令是rexMatchp,函数形式为rexMatchp(t_patternS_target),这个命令将在第二个参数中查找满足第一个参数(模式)的条件,如果找到返回真值,否则返回假值。
▪正则表达式(pattern)的组成字符
语法含义
c匹配任意非特殊字符
.匹配任意字符
\用在特殊字符前面代表特殊字符本身,用在<,>,(,),and1,...,9,的含义在下面描述
[c...]一对方括号中包含一些字符将匹配括号中的任意一个字符,如果第一个字符是^则表示不匹配括号中的所有字符,[a-z]表示匹配a到z之间的任一字符,"-”表示范围。
*用在一个以上描述的字符或pattern后表示匹配该字符或pattern0次或多次。
+类似*,区别在于匹配至少一次
\(..\)如果包含在这个符号中的字符串匹配上了,被匹配的字符可以被提取出来(最多支持9中匹配)
\n和上一个符号对应,反斜杠后跟一个数字将可以提前到上一个符合保留的字符串
\<...\>这个符号表示完全匹配一个字符串的开始和结尾
rs2个正则表达式的组合将尽可能多的匹配r并匹配一个s
^,$^表示字符串的开始,$表示字符串的结尾
▪常用正则匹配函数
rexCompile,rexExecute,rexMatchp,rexSubstitute示例:
使用rexCompile和rexExecute实现开头的示例
lStr='("hello""whenuser""usercome""ffuser""ppuserd""uster");
lRes=nil
rexCompile("user")
foreach(itemlStr
if(rexExecute(item)then
lRes=cons(itemlRes)
println(item)
)
)
将得到和前一个示例一样的结果。
示例:
使用rexSubstitute提取字符,在给定格式的列表中提取symbol名字和对应的坐标
lStr=list("C17x855.00y-2790.00""C676x3499.50y-2676.40""Q690x3406.00y-2701.00"“C666x3535.00y-3135.00”“C785x1929.00y-3750.00”“U628x3865.00y-2025.00”“C737x3010.00y-3155.00”“R754x2770.00y-2730.00”)
rexCompile("\\([A-Z]+[0-9]+\\)x\\([0-9.-]+\\)y\\([0-9.-]+\\)");\\(...\\)结构表示匹配的部分将可以用\\1..9提取出来
;[A-Z]表示匹配A~Z的字符,+表示至少有一个这样的字符
foreach(itemlStr
when(rexExecute(item)
str1=rexSubstitute("\\1")
str2=rexSubstitute("\\2")
str3=rexSubstitute("\\3")
printf("%s<->%s<->%s\n"str1str2str3)
)
);
将输出:
C17<->855.00<->-2790.00
C676<->3499.50<->-2676.40
Q690<->3406.00<->-2701.00
C785<->1929.00<->-3750.00
U628<->3865.00<->-2025.00
C737<->3010.00<->-3155.00
R754<->2770.00<->-2730.00
▪更多示例,参考Skill正则表达式应用举例
Skill正则表达式应用举例
处理DanglingLineReport
allegro的report命令在reportdanglingline的时候也会同时reportdanglingvia出来。
如果你record过script,就会发现产生danglinglinereport的allegro命令是reports"DanglingLinesReport"。
这个命令会在当前allegro工作的文件夹下产生一个叫dangling_lines.rpt的文件。
;------------------------------------------------
<>
PowerTOP*(7710.00-1865.00)to*(6705.00-1615.00)
GNDBOTTOM*(7890.00-1774.00)to*(6575.00-2045.00)
1V5INT3*(7860.00-1930.00)to*(6675.00-2660.00)
12VINT5*(7830.00-1930.00)to*(6705.00-2660.00)
<>
GNDVIA24C12P(5505.00-320.00)
1V5VIA24C12P(5465.00-320.00)
现在我想用正则表达式来找到Via的信息,而排除line的以及一些其它的文字信息。
下面是我想到的patten:
"^[A-Z0-9_]+[]+[A-Z0-9_]+[]+([-0-9.]+[-0-9.]+)$"
在skill环境下简单试一下
rexMatchp("^[A-Z0-9_<>*]+[]+[A-Z0-9_]+[]+([-0-9.]+[-0-9.]+)$"“1V5
VIA24C12P(5465.00-320.00)”)=>t
rexMatchp("^[A-Z0-9_<>*]+[]+[A-Z0-9_]+[]+([-0-9.]+[-0-9.]+)$"“1V5VIA24C12P(5465.00-320.00)to(5465.00-320.00)”)=>nil
所以是满足我们的要求的!
完整的提取程序:
axlShell("reports\"DanglingLinesReport\"")
pDanglingFile=infile("./dangling_lines.rpt")
dl_list=nil
unless(getc(pDanglingFile)
axlMsgPut("-----ErrorsfoundinDanglingLineReport-----")
while(gets(dl_entrypDanglingFile)
when(rexMatchp("^[A-Z0-9_<>*]+[]+[A-Z0-9_]+[]+([-0-9.]+[-0-9.]+).$"dl_entry);;因为gets读进来的dl_entry还带了个"\n",所以必须在之前定义的patten后面再加上一个“."来匹配它
dl_entry=buildString(parseString(dl_entry)"");;因为report结果里面的vianet,padstack以及坐标间隔很大,这个让间隔变小一点
dl_list=cons(dl_entrydl_list)
)
)
close(pDanglingFile)
dl_list=sort(dl_listnil);根据字符串大小的默认排序
)
这样就得到了danglingvia的列表了。
接下来的操作就随个人了,比如把它显示到一个form里面。
另一个例子
"From:
C803.1(3313.0002553.921)To:
U1802.C3(7321.024-1296.024)"
rexCompile("\\(([-0-9.]+[-0-9.]+)\\)[^(]+\\(([-0-9.]+[-0-9.]+)\\)")
这样就可以得到带括号的坐标
rexCompile("(\\([-0-9.]+[-0-9.]+\\))[^(]+(\\([-0-9.]+[-0-9.]+\\))")
得到不带括号的坐标
特殊字符,注释,空格,圆括号和其它标记法的使用
▪特殊字符
SKill中的特殊字符列表
字符全名含义
\反斜杠辅助输出特殊字符
()圆括号组织数据列表和调用函数列表
[]中括号数组索引,超级右中括号
{}大括号使用progn时组织一系列表达式
'单引号单引号中的表达式不会被解析
"双引号字符串分界符
逗号列表中可选的元素分界符;在反引号作用范围内使用强制表达式解析
;分号行注释
:
冒号位分隔符,范围操作
.点号getq操作
+,–,*,/算术运算算术运算符;同时"/*"和"*/"组合也用于多行注释
!
^,&,|逻辑运算逻辑运算符
<,>,=关系运算比较运算,赋值以及位运算
##用在第一列表示信号的特别解析
@@用在第一个字符表示保留字;另外在反引号作用范围内使用将强制表达式解析
问号如果是第一个字符表示关键字
`反引号引号内的表达式不被解析
%百分号
$-保留为将来使用
[注]:
输出这些特殊字符都需要在字符前加"\"。
▪注释
▪行注释方法,使用分号";",注释范围在分号当前行。
▪多行注释,使用"/*"和"*/"对,注释范围在这这对符号内。
▪空格,空格的限制比较少,只是要注意下面几个情况
▪函数名和跟在后面的圆括号之间不能有空格,如max(42)是对的,而max(42)则是错的;
▪表示负数的符号"-"和数字之间不能有空格,如-5,-(a*b)有效,而-5,-(a*b)无效;
▪表示算术运算的"+-*/"在2个数字之间的位置要对称,如a-b,a-b有效,而a-b无效。
▪圆括号
▪圆括号在skill中用于函数调用,分隔多个表达式,控制表达式的解析顺序
▪skill中调用函数有2种方式,max(ab)和(maxab)都有效。
▪超级右中括号,不推荐使用
▪在使用了很多"("的表达式后,可以用"]"来代表很多个用于结尾的")"。
如f1(f2(f3(f4(x))))等效于f1(f2(f3(f4(x]。
▪反引号,逗号和逗号加@
示例1.
y=1
'(xyz)=>(xyz);反引号使得表达式不被解析,所以其中的y不会被1代替
'(x,yz)=>(x1z);增加一个逗号在反引号表达式中,逗号后面的表达式将被解析
示例2.
x=1
y='(abc)
'(,x,yz)=>(1(abc)z);逗号后的表达式都被解析了
'(,x,@yz)=>(1abcz);",@"的作用和逗号一样,只是被解析对象是列表,且解析出来的元素代替了原来的列表
▪续行符"\"
▪使用"\"可以让在一行的文字多行表示,如
string="Thisis\
atest."=>"Thisisatest."
▪初始化列表的最大长度6000,但是在程序运行中列表的长度无限制。
文件系统接口
▪路径
▪绝对路径:
Unix中以"/"开始的路径,Windows中以磁盘"C:
D:
..."开始的路径
▪相对路径,不是绝对路径的情况就是相对路径
▪以"~/"开始的路径表示被查询的路径是用户的home文件夹;
▪以"~username"开始的路径,如果username正好是一个用户的名字,那么被查询的路径将是该用户的home文件夹;
▪以"./"开始的路径表示被查询的位置是当前的工作目录
▪以"../"开始的路径表示被查询的位置为当前工作目录的父文件夹
▪Skill路径
▪skill支持用户定义若干不同的路径来存放skill源文件,并通过skill的路径管理函数来设置各个路径的访问顺序。
如果同一个文件在不同路径下都存在,按照先到先得原则,即使用第一个被找到的文件。
▪设置skill查询路径的函数setSkillPath,如setSkillPath(".""~""C:
/Skill"),就设置了3个skill查询路径,先后顺序分别为"."-当前工作路径,"~"-home文件夹,"C:
/Skill"-用户自定义文件夹。
▪获取skill查询路径列表的函数getSkillPath,如setSkillPath(".""~""C:
/Skill");getSkillPath()=>(".""~""C:
/Skill")
▪安装路径
▪获取安装路径函数getInstallPath,如getInstallPath()=>"C:
/Cadence/Psd16.2"
▪检测文件状态
▪检测文件是否存在函数isFile,isFileName
▪检测文件夹是否存在函数isDir
▪检测文件或文件夹的是否可以被读取的函数isReadable
▪检测文件或文件夹的是否可以被写入的函数isWritable
▪路径操作
▪生成和删除文件夹
▪createDir(arg),如createDir("c:
/temp/skill"),将在c:
/temp下创建一个skill文件夹;
▪deleteDir(arg),如deleteDir("c:
/temp/skill"),将删除这个skill文件夹,如果这是个空文件夹,且用户具有删除它的权限。
▪删除文件函数deleteFile
▪获取指定文件夹下所有文件名函数getDirFiles
▪获取当前工作目录getWorkingDir
▪改变工作目录changeWorkingDir
端口
所有数据的输入输出都是经由一个被称为端口的东西实现的。
预定义的标准端口
端口名作用
piport标准输入端口,等同于C中的stdin
poport标准输出端口,等同于C中的stdout
errport错误输出端口,等同于C中的stderr
ptport跟踪信息端口,等同于C中的stderr
▪打开端口
▪打开一个文件读取端口infile
infile("~/test/input.il")=>port:
"~/test/input.il"
▪打开一个文件输出端口outfile
p=outfile("~/test/out.il""w")=>port:
"~/test/out.il"
▪关闭端口close
p=outfile("~/test/out.il""w")=>port:
"~/test/out.il"
close(p)
I/O
▪输出
▪非格式化输出
print("hello");输出"hello"
println("hello");输出"hello"加换行
▪格式化输出
常见格式化输出规范
格式参数类型输出结果
%dfixnum十进制整数
%ofixnum八进制整数
%xfixnum十六进制整数
%fflonum浮点数,格式为[-]ddd.ddd
%eflonum浮点数,格式为[-]d.ddde[-]ddd
%gflonum不改变浮点数精度的情况下,以最少的空间表示
%sstring,symbol输出字符串
%cstring,symbol输出第一个字符
%nfixnum,flonum数字
%Llist数据的默认形式输出
%Plist点Point
%BlistBox
示例
printf("hello,%s""Willy")=>"hello,Willy"
printf("%d==%x"2020)=>"20==14";把一个十进制书转换成16
sprintf(sMsg"hello,%s""You")=>sMsg="hello,You"
fprintf(port"1stline,%dwords"10);输出"1stline,10words"到文件
printf("fileis