基于PLY的STL文件基本信息统计方法
1、摘要
STL文件是快速成型设备中常用的文件格式,随着3D打印技术的发展,STL格式文件的应用日益广泛。Python语言具有丰富和强大的类库,其语言简洁而清晰,因而Python语言越来越受欢迎。PLY是具名的LEX、YACC的Python版本,本文介绍了利用PLY模块对STL文件进行基本信息统计。
KeyWord:PLY、语法分析、词法分析、STL
2、简介
计算机语言是计算机软件的系统的基础,经过几十年的发展,实现了从低级语言到高级语言的转变。原始的机器语言,到低级的汇编语言,它们虽然可以运行,但是也存在很多问题,比如在程序移植的过程中,往往会出现不兼容的情况。高级语言的出现,使得计算机程序设计语言不再过度地依赖特定的机器或环境,从高级语言翻译成机器可执行的语言就显得相当重要。构造一个高级语言编译器,需要构造相应的此法及语法分析器,PLY模块可以帮助我们实现词法及语法的分析。
2.1 PLY简介
PLY是LEX与YACC的Python版,包含了LEX与YACC的大部分特性。PLY模块包含两个独立的模块:lex.py和yacc.py。lex.py模块用来将输入字符通过一系列的正则表达式分解成标记序列,yacc.py通过一些上下文无关的文法来识别编程语言语法。yacc.py使用LR解析法,并使用LALR(1)算法(默认)或者SLR算法生成分析表。
2.1.1 PLY.LEX基本原理与实践
Lex.py用来将输入字符串标记化。首先,将字符串分割成独立的标记(token),这些token由不同的名称表示,然后将名称和值组合起来形成一个二元组。例如:
tokens = (
'NAME','NUMBER',
)
literals = ['=','+','-','*','/', '(',')']
# Tokens
t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' #词法描述规则1
def t_NUMBER(t): #词法描述规则2
r'\d+'
t.value = int(t.value)
return t
t_ignore = " \t"
def t_newline(t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
def t_error(t): #出错处理
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
# Build the lexer
import ply.lex as lex
lex.lex()
其中tokens是强制词法单元类型列表的名称,强制描述词法规则的变量名格式为t_[TOKENNAME],在此例中有两种类型:NUMBER和NAME。NUMBER定义为\d+,匹配整数,NAME定义为a-zA-Z_][a-zA-Z0-9_],匹配一般标识符。词法描述规则中,规则1不能自定义操作,规则2可以自定义操作,规则2中的参数列表必须为单个参数,并且只能返回t,若不返回则表示丢弃该token。最后调用lex()即可完成词法分析。
2.1.2 PLY.yacc 基本原理与实践
YACC用于对语言进行语法分析。语法通常用BNF范式表达,用的分析技术是LALR分析法,LALR分析法是LR分析法的一种改进分析法。LR(K)分析,是指从左至右扫描和自底向上的语法分析,且在分析的每一步,只须根据分析栈当前已移进和归约出的全部文法符号,并至多再向前查看K个输入符号,就能确定相对于某一产生式左部符号的句柄是否已在分析栈的顶部形成,从而也就可以确定当前所应采取的分析动作 (是移进还是按某一产生式进行归约等)。例如:
简单算术表达式文法:
E : E + T
| E - T
| T
T : T * F
| T / F
| F
F : N
| ( E )
每个文法规则被描述为一个函数,这个函数的文档字符串描述了对应的上下文无关文法的规则。函数体用来实现规则的语义动作。每个函数都会接受一个参数p,这个参数是一个序列(sequence),包含了组成这个规则的所有的语法符号,p[i]是规则中的第i个语法符号。比如:
语法说明中的第一个为起始规则,也可以通过关键字参数传递给yacc以指定起始文法规则:
yacc.yacc(start = 'rule_name')
2.2 STL文件简介
STL文件是在计算机图形应用系统中,用于表示三角形网格的一种文件格式。STL文件凭借其简单的格式,在许多领域得到应用,特别是在快速成型系统中的应用。STL文件有两种:一种为ASCII格式,另一种为二进制格式。在这里只介绍ASCII格式的STL文件。
STL的文件结构如下:
solid filename //文件名
facet normal x y z //三角形法矢量
outer loop
vertex x y z //第一个点
vertex x y z //第二个点
vertex x y z //第三个点
endloop
endfacet
……..
endsolid filename
3、词法分析
分析STL文件的文件结构,将词法单元类型分成5类:KEYWORD、RPARAM、LPARAM、NAME、NUMBER。词法采用正则表达式描述,详细定义分别如下:
KEYWORD:normal | outer | vertex
RPARAM:solid | facet | loop
LPARAM:endsolid | endfacet | endloop
NAME:[a-zA-Z_][a-zA-Z0-9_]*
NUMBER:(-?\d+)(\.\d+)?(e-?\d+)?
词法分析结果如下:
LexToken(RPARAM,'solid',1,0)
LexToken(NAME,'OBJECT',1,6)
LexToken(RPARAM,'facet',2,15)
LexToken(KEYWORD,'normal',2,21)
LexToken(NUMBER,-0.0,2,28)
LexToken(NUMBER,-1.0,2,31)
LexToken(NUMBER,0.0,2,34)
LexToken(KEYWORD,'outer',3,40)
LexToken(RPARAM,'loop',3,46)
LexToken(KEYWORD,'vertex',4,57)
LexToken(NUMBER,-24.721731185913086,4,64)
LexToken(NUMBER,-6.938085079193115,4,84)
LexToken(NUMBER,0.0,4,104)
LexToken(KEYWORD,'vertex',5,112)
LexToken(NUMBER,-21.674671173095703,5,119)
LexToken(NUMBER,-6.938085079193115,5,139)
……..
从词法分析结果中可以看出,扫描字符串的过程是从左至右依次进行。词法分析代码参见附录B
4、语法分析
STL文件格式比较简单,其文法也相应比较简单。采用BNF范式描述STL文件的文件结构:
Rule 0 S' -> start
Rule 1 start -> RPARAM NAME facet LPARAM NAME
Rule 2 facet -> facet facet
Rule 3 facet -> RPARAM norm out LPARAM
Rule 4 norm -> KEYWORD NUMBER NUMBER NUMBER
Rule 5 out -> KEYWORD lp
Rule 6 lp -> RPARAM vertex LPARAM
Rule 7 vertex -> point point point
Rule 8 point -> KEYWORD NUMBER NUMBER NUMBER
在采用LALR分析法时,出现移近规约冲突:
(2) facet -> facet facet .
(2) facet -> facet . facet
(2) facet -> . facet facet
(3) facet -> . RPARAM norm out LPARAM
! shift/reduce conflict for RPARAM resolved as shift
LPARAM reduce using rule 2 (facet -> facet facet .)
RPARAM shift and go to state 4
! RPARAM [ reduce using rule 2 (facet -> facet facet .) ]
facet shift and go to state 9
默认采用移进解决这种移进规约冲突。
具体实现参见附录B
语法分析结果如下;
norm : KEYWORD NUMBER NUMBER NUMBER
point : KEYWORD NUMBER NUMBER NUMBER
point : KEYWORD NUMBER NUMBER NUMBER
point : KEYWORD NUMBER NUMBER NUMBER
vertex : point point point
lp : RPARAM vertex LPARAM
out : KEYWORD lp
facet : RPARAM norm out LPARAM
…….
facet : facet facet
facet : facet facet
facet : facet facet
…..
start : RPARAM NAME facet LPARAM NAME
从分析结果中可以看出语法分析中各规则归约顺序:首先是Rule 4,接着是3个Rule 8,然后Rule 7-> Rule 6-> Rule 5,跟着是Rule 3。如此分析完成一个三角形块。所有块分析完成后,应用Rule 2,最终应用Rule 1完成整个文件的分析。具体分析表参见附录C,分析过程参见附录D
5、信息统计
在这里我们统计网格中的三角形个数和三角形的顶点数以及网格的表面积,虽然三角形顶点数可由三角形个数乘3得到,但是这里提供了语法分析时统计的手段。在每次对Rule 8进行规约时,顶点数加1,同时保存顶点用于表面积的计算;对Rule 3进行规约时,三角形个数加1,同时计算出三角形的面积,并对三角形面积进行累加。
由三角形的三个顶点A(x0,y0,z0),B(x1,y1,z1),C(x2,y2,z2)计算三角形的面积S。首先计算出三条边的长度:
令,由海伦公式可得:
6、测试及分析
用计算机图形系统软件绘制一些三维文件,然后导出ASCII的STL格式文件作为测试用例。测试结果如下:
Cube.stl
---------------------------------------------------------------------------------------
object informatioin:
vertex: 84 facet: 28 surface area: 146.5441114077912
---------------------------------------------------------------------------------------
cy.stl
---------------------------------------------------------------------------------------
object informatioin:
vertex: 4740 facet: 1580 surface area: 1841.906043447056
---------------------------------------------------------------------------------------
shouji.stl
---------------------------------------------------------------------------------------
object informatioin:
vertex: 34542 facet: 11514 surface area: 1971.3863130454672
---------------------------------------------------------------------------------------
这三个测试用例都通过了测试。第一个、及第二个测试用例,内容较少,用于分析统计的时间可以忽略不计。第三个测试用例的容量较大,运行时有少许延时,若通过编译转换成C语言代码运行,可改善延时问题。
7、参考文献:
[1] 姚泽勤, 柏又青. 利用 LEX 及 YACC 实现嵌入式 SQL 分析器[J]. 航空计算技术, 2002, 32(1): 55-58.
[2] 肖任贤、张军舰、冯浩、潘海鹏, STL文件读取显示与操作, 陶瓷学报.2011(2)
[3] Lesk M E, Schmidt E. lex: A lexical analyzer generator[M]. Bell Laboratories, 1987.
[4] Johnson S C. Yacc: Yet another compiler-compiler[M]. Murray Hill, NJ: Bell Laboratories, 1975.
[5] Beazley D M. Ply, python lex-yacc (2001)[J]. UR L http://www. dabeaz. com/ply.
[6] Amiguet M. Teaching compilers with python[J]. 2010.
8、附录:(代码)
8.1 附录A——stlcount.py
1 #------------------------------------------------------------- 2 #stlcount.py 3 # 4 # STL文件信息统计 5 #------------------------------------------------------------- 6 import math 7 8 #小三角片数 9 c_facet=0 10 11 #表面积 12 s_all=0 13 14 #点数 15 c_vertex=0 16 17 18 #保存三个点 19 v_points=[] 20 21 b_print_yacc=False 22 b_print_lex=False 23 24 #初始化 25 def init_countstl(): 26 global c_facet,s_all,c_vertex,v_points 27 c_facet=0 28 s_all=0 29 c_vertex=0 30 v_points=[] 31 32 def display(a,b,c): 33 print("--------------------------------------------------------------------------") 34 print("object informatioin:") 35 print("\tvertex: "+str(a)+"\tfacet: "+str(b)+"\tsurface area: "+str(c)) 36 print("--------------------------------------------------------------------------") 37 38 def cal_area(p0,p1,p2): 39 A=[0,0,0] 40 B=[0,0,0] 41 C=[0,0,0] 42 A[0]=p1[0]-p0[0] 43 B[0]=p2[0]-p0[0] 44 C[0]=p2[0]-p1[0] 45 A[1]=p1[1]-p0[1] 46 B[1]=p2[1]-p0[1] 47 C[1]=p2[1]-p1[1] 48 A[2]=p1[2]-p0[2] 49 B[2]=p2[2]-p0[2] 50 C[2]=p2[2]-p1[2] 51 a=math.sqrt(A[0]**2+A[1]**2+A[2]**2) 52 b=math.sqrt(B[0]**2+B[1]**2+B[2]**2) 53 c=math.sqrt(C[0]**2+C[1]**2+C[2]**2) 54 p=(a+b+c)/2.0 55 return math.sqrt(p*(p-a)*(p-b)*(p-c)) 56
8.2 附录B——stl.py
1 # ----------------------------------------------------------------------------- 2 # stl.py 3 # 4 # A simple calculator with variables. This is from O'Reilly's 5 # "Lex and Yacc", p. 63. 6 # ----------------------------------------------------------------------------- 7 8 import stlcount as cn 9 10 #------------------------------------------------------------------------------ 11 #词法分析 12 #------------------------------------------------------------------------------ 13 14 15 16 tokens = ( 17 'KEYWORD','RPARAM','LPARAM','NAME','NUMBER' 18 ) 19 20 #literals = ['=','+','-','*','/', '(',')'] 21 22 # Tokens 23 24 def t_KEYWORD(t): 25 r"normal | outer | vertex" 26 return t 27 28 def t_RPARAM(t): 29 r"solid | facet | loop" 30 return t 31 32 def t_LPARAM(t): 33 r"endsolid | endfacet | endloop" 34 return t 35 36 def t_NAME(t): 37 r'[a-zA-Z_][a-zA-Z0-9_]*' 38 return t 39 40 def t_NUMBER(t): 41 r'(-?\d+)(\.\d+)?(e-?\d+)?' 42 t.value = float(t.value) 43 return t 44 45 t_ignore = " \t" 46 47 def t_newline(t): 48 r'\n+' 49 t.lexer.lineno += t.value.count("\n") 50 51 def t_error(t): 52 print("Illegal character '%s'" % t.value[0]) 53 t.lexer.skip(1) 54 55 # Build the lexer 56 import ply.lex as lex 57 lexer=lex.lex() 58 59 #====================================================================== 60 61 def p_start(p): 62 r'start : RPARAM NAME facet LPARAM NAME' 63 if cn.b_print_yacc: 64 print("start : RPARAM NAME facet LPARAM NAME") 65 cn.display(cn.c_vertex,cn.c_facet,cn.s_all) 66 67 def p_facet(p): 68 r'facet : facet facet' 69 if cn.b_print_yacc: 70 print('facet : facet facet') 71 72 def p_facet1(p): 73 r'facet : RPARAM norm out LPARAM' 74 if cn.b_print_yacc: 75 print('facet : RPARAM norm out LPARAM') 76 cn.c_facet=cn.c_facet+1 77 s_single=cn.cal_area(cn.v_points[0],cn.v_points[1],cn.v_points[2]) 78 if s_single<0: 79 print("****************************ERROR*******************************") 80 cn.s_all=cn.s_all+s_single 81 if cn.b_print_yacc: 82 print("area:",end='\t') 83 print(cn.s_all) 84 cn.v_points=[] 85 86 87 def p_norm(p): 88 r'norm : KEYWORD NUMBER NUMBER NUMBER' 89 if cn.b_print_yacc: 90 print("norm : KEYWORD NUMBER NUMBER NUMBER") 91 92 def p_out(p): 93 r'out : KEYWORD lp' 94 if cn.b_print_yacc: 95 print("out : KEYWORD lp") 96 97 def p_lp(p): 98 r'lp : RPARAM vertex LPARAM' 99 if cn.b_print_yacc: 100 print('lp : RPARAM vertex LPARAM') 101 102 def p_vertex(p): 103 r'vertex : point point point' 104 if cn.b_print_yacc: 105 print('vertex : point point point') 106 107 def p_point(p): 108 r'point : KEYWORD NUMBER NUMBER NUMBER' 109 if cn.b_print_yacc: 110 print('point : KEYWORD NUMBER NUMBER NUMBER') 111 cn.c_vertex=cn.c_vertex+1 112 cn.v_points.append([p[2],p[3],p[4]]) 113 114 115 def p_error(p): 116 if p: 117 print("Syntax error at '%s'" % p.value) 118 else: 119 print("Syntax error at EOF") 120 121 import ply.yacc as yacc 122 yacc.yacc() 123 124 125 def stl_exec(s,blex=False,byacc=False): 126 cn.b_print_lex=blex 127 cn.b_print_yacc=byacc 128 cn.init_countstl() 129 if cn.b_print_lex: 130 print("----------------------------------------------------------------------") 131 print("\t\tlex") 132 print("----------------------------------------------------------------------") 133 lexer.input(s) 134 for st in lexer: 135 print(st) 136 if cn.b_print_yacc: 137 print("----------------------------------------------------------------------") 138 print("\t\tyacc") 139 print("----------------------------------------------------------------------") 140 yacc.parse(s)
8.3 附录C——parsetab.py
1 # parsetab.py 2 # This file is automatically generated. Do not edit. 3 _tabversion = '3.2' 4 5 _lr_method = 'LALR' 6 7 _lr_signature = b'|:{\xf5@\x08\xce\xd8d\x055eAN\xff\x13' 8 9 _lr_action_items = {'NAME':([1,8,],[3,13,]),'KEYWORD':([4,7,15,18,21,24,27,],[6,11,19,-4,19,19,-8,]),'NUMBER':([6,10,14,19,22,25,],[10,14,18,22,25,27,]),'LPARAM':([5,9,12,16,17,20,23,26,27,],[8,-2,17,-5,-3,23,-6,-7,-8,]),'$end':([2,13,],[0,-1,]),'RPARAM':([0,3,5,9,11,17,],[1,4,4,4,15,-3,]),} 10 11 _lr_action = { } 12 for _k, _v in _lr_action_items.items(): 13 for _x,_y in zip(_v[0],_v[1]): 14 if not _x in _lr_action: _lr_action[_x] = { } 15 _lr_action[_x][_k] = _y 16 del _lr_action_items 17 18 _lr_goto_items = {'norm':([4,],[7,]),'start':([0,],[2,]),'vertex':([15,],[20,]),'point':([15,21,24,],[21,24,26,]),'facet':([3,5,9,],[5,9,9,]),'lp':([11,],[16,]),'out':([7,],[12,]),} 19 20 _lr_goto = { } 21 for _k, _v in _lr_goto_items.items(): 22 for _x,_y in zip(_v[0],_v[1]): 23 if not _x in _lr_goto: _lr_goto[_x] = { } 24 _lr_goto[_x][_k] = _y 25 del _lr_goto_items 26 _lr_productions = [ 27 ("S' -> start","S'",1,None,None,None), 28 ('start -> RPARAM NAME facet LPARAM NAME','start',5,'p_start','E:\\PY\\stl.py',65), 29 ('facet -> facet facet','facet',2,'p_facet','E:\\PY\\stl.py',71), 30 ('facet -> RPARAM norm out LPARAM','facet',4,'p_facet1','E:\\PY\\stl.py',76), 31 ('norm -> KEYWORD NUMBER NUMBER NUMBER','norm',4,'p_norm','E:\\PY\\stl.py',91), 32 ('out -> KEYWORD lp','out',2,'p_out','E:\\PY\\stl.py',96), 33 ('lp -> RPARAM vertex LPARAM','lp',3,'p_lp','E:\\PY\\stl.py',101), 34 ('vertex -> point point point','vertex',3,'p_vertex','E:\\PY\\stl.py',106), 35 ('point -> KEYWORD NUMBER NUMBER NUMBER','point',4,'p_point','E:\\PY\\stl.py',111), 36 ]
8.4 附录D——parser.out
1 Created by PLY version 3.4 (http://www.dabeaz.com/ply) 2 3 Grammar 4 5 Rule 0 S' -> start 6 Rule 1 start -> RPARAM NAME facet LPARAM NAME 7 Rule 2 facet -> facet facet 8 Rule 3 facet -> RPARAM norm out LPARAM 9 Rule 4 norm -> KEYWORD NUMBER NUMBER NUMBER 10 Rule 5 out -> KEYWORD lp 11 Rule 6 lp -> RPARAM vertex LPARAM 12 Rule 7 vertex -> point point point 13 Rule 8 point -> KEYWORD NUMBER NUMBER NUMBER 14 15 Terminals, with rules where they appear 16 17 KEYWORD : 4 5 8 18 LPARAM : 1 3 6 19 NAME : 1 1 20 NUMBER : 4 4 4 8 8 8 21 RPARAM : 1 3 6 22 error : 23 24 Nonterminals, with rules where they appear 25 26 facet : 1 2 2 27 lp : 5 28 norm : 3 29 out : 3 30 point : 7 7 7 31 start : 0 32 vertex : 6 33 34 Parsing method: LALR 35 36 state 0 37 38 (0) S' -> . start 39 (1) start -> . RPARAM NAME facet LPARAM NAME 40 41 RPARAM shift and go to state 1 42 43 start shift and go to state 2 44 45 state 1 46 47 (1) start -> RPARAM . NAME facet LPARAM NAME 48 49 NAME shift and go to state 3 50 51 52 state 2 53 54 (0) S' -> start . 55 56 57 58 state 3 59 60 (1) start -> RPARAM NAME . facet LPARAM NAME 61 (2) facet -> . facet facet 62 (3) facet -> . RPARAM norm out LPARAM 63 64 RPARAM shift and go to state 4 65 66 facet shift and go to state 5 67 68 state 4 69 70 (3) facet -> RPARAM . norm out LPARAM 71 (4) norm -> . KEYWORD NUMBER NUMBER NUMBER 72 73 KEYWORD shift and go to state 7 74 75 norm shift and go to state 6 76 77 state 5 78 79 (1) start -> RPARAM NAME facet . LPARAM NAME 80 (2) facet -> facet . facet 81 (2) facet -> . facet facet 82 (3) facet -> . RPARAM norm out LPARAM 83 84 LPARAM shift and go to state 8 85 RPARAM shift and go to state 4 86 87 facet shift and go to state 9 88 89 state 6 90 91 (3) facet -> RPARAM norm . out LPARAM 92 (5) out -> . KEYWORD lp 93 94 KEYWORD shift and go to state 11 95 96 out shift and go to state 10 97 98 state 7 99 100 (4) norm -> KEYWORD . NUMBER NUMBER NUMBER 101 102 NUMBER shift and go to state 12 103 104 105 state 8 106 107 (1) start -> RPARAM NAME facet LPARAM . NAME 108 109 NAME shift and go to state 13 110 111 112 state 9 113 114 (2) facet -> facet facet . 115 (2) facet -> facet . facet 116 (2) facet -> . facet facet 117 (3) facet -> . RPARAM norm out LPARAM 118 119 ! shift/reduce conflict for RPARAM resolved as shift 120 LPARAM reduce using rule 2 (facet -> facet facet .) 121 RPARAM shift and go to state 4 122 123 ! RPARAM [ reduce using rule 2 (facet -> facet facet .) ] 124 125 facet shift and go to state 9 126 127 state 10 128 129 (3) facet -> RPARAM norm out . LPARAM 130 131 LPARAM shift and go to state 14 132 133 134 state 11 135 136 (5) out -> KEYWORD . lp 137 (6) lp -> . RPARAM vertex LPARAM 138 139 RPARAM shift and go to state 16 140 141 lp shift and go to state 15 142 143 state 12 144 145 (4) norm -> KEYWORD NUMBER . NUMBER NUMBER 146 147 NUMBER shift and go to state 17 148 149 150 state 13 151 152 (1) start -> RPARAM NAME facet LPARAM NAME . 153 154 $end reduce using rule 1 (start -> RPARAM NAME facet LPARAM NAME .) 155 156 157 state 14 158 159 (3) facet -> RPARAM norm out LPARAM . 160 161 RPARAM reduce using rule 3 (facet -> RPARAM norm out LPARAM .) 162 LPARAM reduce using rule 3 (facet -> RPARAM norm out LPARAM .) 163 164 165 state 15 166 167 (5) out -> KEYWORD lp . 168 169 LPARAM reduce using rule 5 (out -> KEYWORD lp .) 170 171 172 state 16 173 174 (6) lp -> RPARAM . vertex LPARAM 175 (7) vertex -> . point point point 176 (8) point -> . KEYWORD NUMBER NUMBER NUMBER 177 178 KEYWORD shift and go to state 19 179 180 vertex shift and go to state 18 181 point shift and go to state 20 182 183 state 17 184 185 (4) norm -> KEYWORD NUMBER NUMBER . NUMBER 186 187 NUMBER shift and go to state 21 188 189 190 state 18 191 192 (6) lp -> RPARAM vertex . LPARAM 193 194 LPARAM shift and go to state 22 195 196 197 state 19 198 199 (8) point -> KEYWORD . NUMBER NUMBER NUMBER 200 201 NUMBER shift and go to state 23 202 203 204 state 20 205 206 (7) vertex -> point . point point 207 (8) point -> . KEYWORD NUMBER NUMBER NUMBER 208 209 KEYWORD shift and go to state 19 210 211 point shift and go to state 24 212 213 state 21 214 215 (4) norm -> KEYWORD NUMBER NUMBER NUMBER . 216 217 KEYWORD reduce using rule 4 (norm -> KEYWORD NUMBER NUMBER NUMBER .) 218 219 220 state 22 221 222 (6) lp -> RPARAM vertex LPARAM . 223 224 LPARAM reduce using rule 6 (lp -> RPARAM vertex LPARAM .) 225 226 227 state 23 228 229 (8) point -> KEYWORD NUMBER . NUMBER NUMBER 230 231 NUMBER shift and go to state 25 232 233 234 state 24 235 236 (7) vertex -> point point . point 237 (8) point -> . KEYWORD NUMBER NUMBER NUMBER 238 239 KEYWORD shift and go to state 19 240 241 point shift and go to state 26 242 243 state 25 244 245 (8) point -> KEYWORD NUMBER NUMBER . NUMBER 246 247 NUMBER shift and go to state 27 248 249 250 state 26 251 252 (7) vertex -> point point point . 253 254 LPARAM reduce using rule 7 (vertex -> point point point .) 255 256 257 state 27 258 259 (8) point -> KEYWORD NUMBER NUMBER NUMBER . 260 261 KEYWORD reduce using rule 8 (point -> KEYWORD NUMBER NUMBER NUMBER .) 262 LPARAM reduce using rule 8 (point -> KEYWORD NUMBER NUMBER NUMBER .) 263 264 WARNING: 265 WARNING: Conflicts: 266 WARNING: 267 WARNING: shift/re
8.5 附录E——cstl.py
1 import sys 2 largv=len(sys.argv) 3 bLex=False 4 bYacc=False 5 if largv==1: 6 filename=input('please input the name of file\n>>>') 7 else: 8 if largv>1: 9 filename=sys.argv[1] 10 if largv>2: 11 if sys.argv[2]=='L': 12 bLex=True 13 bYacc=False 14 else: 15 if sys.argv[2]=='Y': 16 bLex=False 17 bYacc=True 18 else: 19 if sys.argv[2]=='YL' or sys.argv[2]=='LY': 20 bLex=True 21 bYacc=True 22 def run(): 23 try: 24 file=open(filename).read() 25 import stl 26 stl.stl_exec(file,bLex,bYacc) 27 except: 28 print('OPENFILE ERROR!') 29 exit() 30 31 run()