Advertisement
Guest User

Untitled

a guest
Mar 21st, 2019
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.52 KB | None | 0 0
  1. import io
  2. import keyword
  3.  
  4. from ply import lex
  5. from ply import yacc
  6.  
  7. from logging import getLogger, basicConfig, DEBUG, INFO
  8.  
  9. log = getLogger(__name__)
  10.  
  11. reserved = """
  12. CONST ENUM STRUCT OPAQUE UNSIGNED STRING TYPEDEF CASE DEFAULT VOID
  13. UNION SWITCH BOOL HYPER LONG INT NETOBJ TRUE FALSE
  14. PROGRAM VERSION
  15. """.strip().split()
  16.  
  17. tokens = reserved + """
  18. ID TYPEID ICONST
  19. EQ LT GT MINUS PLUS TIMES
  20. SEMI COLON COMMA
  21. LPAREN RPAREN
  22. LBRACKET RBRACKET
  23. LBRACE RBRACE
  24. """.strip().split()
  25.  
  26. t_ignore = " \t\x0c"
  27.  
  28. ngname = keyword.kwlist + dir(__builtins__)
  29.  
  30.  
  31. def t_NEWLINE(t):
  32. r'\n+'
  33.  
  34.  
  35. t_TIMES = r'\*'
  36. t_MINUS = r'\-'
  37. t_PLUS = r'\+'
  38. t_LT = r'<'
  39. t_GT = r'>'
  40. t_EQ = r'='
  41. t_LPAREN = r'\('
  42. t_RPAREN = r'\)'
  43. t_LBRACKET = r'\['
  44. t_RBRACKET = r'\]'
  45. t_LBRACE = r'\{'
  46. t_RBRACE = r'\}'
  47. t_COMMA = r','
  48. t_SEMI = r';'
  49. t_COLON = r':'
  50. t_ICONST = r'[-+]?(0x?)?\d+'
  51. t_ignore_COMMENT = r'(/\*(.|\n)*?\*/|//[^\n]*\n$)'
  52. t_ignore_PP = r'\#(.)*?\n'
  53. t_ignore_PX = r'\%(.)*?\n'
  54.  
  55. reserved_map = {
  56. "TRUE": "ICONST",
  57. "FALSE": "ICONST",
  58. }
  59. for r in reserved:
  60. reserved_map[r.lower()] = r
  61.  
  62. constmap = {}
  63.  
  64.  
  65. def t_error(t):
  66. log.error("error: %s", t)
  67.  
  68.  
  69. def t_ID(t):
  70. r'[A-Za-z_][\w_]*'
  71. t.type = reserved_map.get(t.value, "ID")
  72. while t.value in ngname:
  73. t.value = t.value + "_"
  74. return t
  75.  
  76.  
  77. def sequence(t, first, second):
  78. if len(t) == first + 1:
  79. t[0] = [t[first]]
  80. elif len(t) == second + 1:
  81. if t[0] is None:
  82. t[0] = [t[first]]
  83. if t[second] is not None:
  84. t[0].extend(t[second])
  85. else:
  86. t[0].append(t[first])
  87.  
  88.  
  89. def valmap(s):
  90. return dict(s)
  91.  
  92.  
  93. def p_statements_1(t):
  94. """statements : statement statements
  95. | statement"""
  96. log.debug("p_statements_1: %s", t)
  97. sequence(t, 1, 2)
  98.  
  99.  
  100. def p_statement(t):
  101. """statement : defconst SEMI
  102. | defenum SEMI
  103. | defstruct SEMI
  104. | typedef SEMI
  105. | union SEMI
  106. | program SEMI"""
  107. log.debug("p_statement_1: %s", t)
  108. t[0] = t[1]
  109.  
  110.  
  111. def p_defconst(t):
  112. """defconst : CONST ID EQ ICONST"""
  113. log.debug("defconst: %s %s", t[2], t[4])
  114. reserved_map[t[2]] = "ICONST"
  115. constmap[t[2]] = t[4]
  116. t[0] = {"const": t[2], "value": t[4]}
  117.  
  118.  
  119. def p_defenum(t):
  120. """defenum : ENUM ID LBRACE enuments RBRACE"""
  121. log.debug("p_defenum: %s %s", t[2], t[4])
  122. reserved_map[t[2]] = "TYPEID"
  123. t[0] = {"enum": t[2], "values": valmap(t[4])}
  124.  
  125.  
  126. def p_enuments(t):
  127. """enuments : enument
  128. | enument COMMA enuments"""
  129. log.debug("p_enuments_1: %s", list(t))
  130. sequence(t, 1, 3)
  131.  
  132.  
  133. def p_enument(t):
  134. """enument : ID EQ ICONST"""
  135. log.debug("p_enuments_2: %s %s", t[1], t[3])
  136. reserved_map[t[1]] = "ICONST"
  137. t[0] = (t[1], t[3])
  138.  
  139.  
  140. def p_struct(t):
  141. """defstruct : STRUCT ID LBRACE structents RBRACE
  142. | STRUCT TYPEID LBRACE structents RBRACE"""
  143. log.debug("p_struct: %s", t[2])
  144. reserved_map[t[2]] = "TYPEID"
  145. t[0] = {"struct": t[2], "entries": t[4]}
  146.  
  147.  
  148. def p_structents(t):
  149. """structents : structent structents
  150. | structent"""
  151. log.debug("p_structents: %s", list(t))
  152. sequence(t, 1, 2)
  153.  
  154.  
  155. def p_structent_1(t):
  156. """structent : typeid ID SEMI
  157. | typeid TYPEID SEMI
  158. | ID ID SEMI"""
  159. log.debug("p_structent_1: %s %s", t[1], t[2])
  160. t[0] = {"name": t[2], "type": t[1], "note": "raw"}
  161.  
  162.  
  163. def p_structent_2(t):
  164. """structent : typeid ID LT ICONST GT SEMI
  165. | typeid ID LT GT SEMI
  166. | typeid ID LBRACKET ICONST RBRACKET SEMI
  167. | typeid ID LBRACKET RBRACKET SEMI"""
  168. log.debug("p_structent_2: %s", list(t))
  169. t[0] = {"name": t[2], "type": t[1], "note": "array"}
  170. if len(t) == 7:
  171. t[0]["length"] = t[4]
  172. if t[3] == "[":
  173. t[0]["fixed"] = True
  174.  
  175.  
  176. def p_structent_3(t):
  177. """structent : ID TIMES ID SEMI
  178. | typeid TIMES ID SEMI"""
  179. log.debug("p_structent_3: %s", list(t))
  180. t[0] = {"name": t[3], "type": t[1], "note": "pointer"}
  181.  
  182.  
  183. def p_typeid(t):
  184. """typeid : TYPEID
  185. | OPAQUE
  186. | UNSIGNED
  187. | UNSIGNED HYPER
  188. | UNSIGNED INT
  189. | UNSIGNED LONG
  190. | STRING
  191. | NETOBJ
  192. | BOOL
  193. | HYPER
  194. | LONG
  195. | INT
  196. | VOID
  197. | STRUCT TYPEID"""
  198. log.debug("p_typeid: %s", t[1])
  199. t[0] = t[1]
  200.  
  201.  
  202. def p_typedef_1(t):
  203. """typedef : TYPEDEF typeid ID
  204. | TYPEDEF typeid TYPEID
  205. | TYPEDEF typeid ID LT ICONST GT
  206. | TYPEDEF typeid ID LT GT
  207. | TYPEDEF typeid ID LBRACKET ICONST RBRACKET"""
  208. log.debug("p_typedef: %s", t[3])
  209. reserved_map[t[3]] = "TYPEID"
  210. t[0] = {"typedef": t[3], "type": t[2]}
  211. if len(t) == 4:
  212. t[0]["note"] = "raw"
  213. else:
  214. t[0]["note"] = "array"
  215. if len(t) == 7:
  216. t[0]["length"] = t[5]
  217. if len(t) > 5 and t[4] == "[":
  218. t[0]["fixed"] = True
  219.  
  220.  
  221. def p_typedef_2(t):
  222. """typedef : TYPEDEF STRUCT ID TIMES ID"""
  223. log.debug("p_typedef_2: %s %s", t[3], t[5])
  224. reserved_map[t[5]] = "TYPEID"
  225. t[0] = {"typedef": t[3], "type": t[5], "note": "pointer"}
  226.  
  227.  
  228. def p_union(t):
  229. """union : UNION ID SWITCH LPAREN typeid ID RPAREN LBRACE cases RBRACE"""
  230. log.debug("p_union: %s %s", t[2], t[5])
  231. reserved_map[t[2]] = "TYPEID"
  232. t[0] = {"union": t[2], "cond": {"type": t[5], "name": t[6]}, "cases": t[9]}
  233.  
  234.  
  235. def p_cases(t):
  236. """cases : case cases
  237. | case"""
  238. log.debug("p_cases: %s", list(t))
  239. sequence(t, 1, 2)
  240.  
  241.  
  242. def p_case(t):
  243. """case : caselabel typeid SEMI
  244. | caselabel
  245. | caselabel ID SEMI
  246. | caselabel ID ID SEMI
  247. | caselabel typeid ID SEMI"""
  248. log.debug("p_case: %s", t[1])
  249. t[0] = {"label": t[1]}
  250. if len(t) != 2:
  251. t[0]["type"] = t[2]
  252. if len(t) == 5:
  253. t[0]["name"] = t[3]
  254.  
  255.  
  256. def p_caselabel_1(t):
  257. """caselabel : CASE ICONST COLON"""
  258. log.debug("p_caselabel: %s", t[2])
  259. t[0] = t[2]
  260.  
  261.  
  262. def p_caselabel_2(t):
  263. """caselabel : DEFAULT COLON"""
  264. log.debug("p_caselabel: %s", t[1])
  265. t[0] = t[1]
  266.  
  267.  
  268. def p_program(t):
  269. """program : PROGRAM ID LBRACE versions RBRACE EQ ICONST"""
  270. log.debug("p_program: %s %s %s", t[2], t[4], t[7])
  271. t[0] = {"program": t[2], "num": t[7], "versions": t[4]}
  272.  
  273.  
  274. def p_versions(t):
  275. """versions : version versions
  276. | version"""
  277. log.debug("p_versions: %s", list(t))
  278. sequence(t, 1, 2)
  279.  
  280.  
  281. def p_version(t):
  282. """version : VERSION ID LBRACE procs RBRACE EQ ICONST SEMI"""
  283. log.debug("p_version: %s id=%s procs=%s", t[2], t[7], t[4])
  284. t[0] = {"version": t[2], "num": t[7], "procs": t[4]}
  285.  
  286.  
  287. def p_procs(t):
  288. """procs : proc procs
  289. | proc"""
  290. log.debug("p_procs: %s", list(t))
  291. sequence(t, 1, 2)
  292.  
  293.  
  294. def p_proc(t):
  295. """proc : typeid ID LPAREN typeid RPAREN EQ ICONST SEMI"""
  296. log.debug("p_proc: %s id=%s arg=%s res=%s", t[2], t[7], t[4], t[1])
  297. t[0] = {"id": t[7], "name": t[2], "arg": t[4], "res": t[1]}
  298.  
  299.  
  300. def p_error(t):
  301. log.error("error: %s", t)
  302.  
  303.  
  304. def parse_file(fp, debug=False, defines={}):
  305. log.debug("defines: %s", defines)
  306. for k, v in defines.items():
  307. log.info("const: %s=%s", k, v)
  308. constmap[k] = str(v)
  309. if isinstance(v, int):
  310. reserved_map[k] = "ICONST"
  311. log.debug("reserved: %s=%s", k, v)
  312. lexer = lex.lex()
  313. parser = yacc.yacc(debug=debug)
  314. if not hasattr(fp, "encoding"):
  315. fp = io.TextIOWrapper(fp)
  316. return yacc.parse(fp.read(), debug=debug)
  317.  
  318.  
  319. def get_lexer(fp):
  320. lx = lex.lex()
  321. lx.input(fp.read())
  322. return lx
  323.  
  324.  
  325. if __name__ == "__main__":
  326. import sys
  327. import yaml
  328. basicConfig(level=DEBUG)
  329. mode = "lex"
  330. defs = {"LM_MAXSTRLEN": 1024, "MAXNAMELEN": 1025, "MAXNETNAMELEN": 255}
  331. # defs = {}
  332. if len(sys.argv) >= 2:
  333. mode = sys.argv[1]
  334. if mode == "lex":
  335. for token in get_lexer(sys.stdin):
  336. log.info("token %s", token)
  337. elif mode == "yacc":
  338. result = parse_file(sys.stdin, debug=True, defines=defs)
  339. log.debug("parsed %s", result)
  340. log.info("const %s", constmap)
  341. sys.stdout.write(yaml.dump(result))
  342. elif mode == "yacc_cpp":
  343. import subprocess
  344. with subprocess.Popen(["cpp"], stdin=subprocess.PIPE,
  345. stdout=subprocess.PIPE) as p:
  346. p.stdin.write(sys.stdin.read().encode('utf-8'))
  347. p.stdin.close()
  348. result = parse_file(p.stdout, debug=False, defines=defs)
  349. log.debug("parsed %s", result)
  350. log.info("const %s", constmap)
  351. sys.stdout.write(yaml.dump(result))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement