nom_lua/
ast.rs

1// Copyright 2017 The nom-lua project developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use std::fmt;
10use std::fmt::{Debug, Display, Formatter};
11
12#[derive(Clone, PartialEq)]
13pub enum ASTNode {
14    Integer(i64),
15    Float(f64),
16    Bool(bool),
17    String(String),
18    Label(String),
19    Name(String),
20    Paren(Box<ASTNode>),
21
22    Block(Vec<ASTNode>, Box<Option<ASTNode>>),
23
24    //Statements
25    EmptyStatement,
26    Break,
27    Goto(Box<ASTNode>),
28    RetStat(Box<Option<ASTNode>>),
29
30    // ArithmeticOps
31    Add(Box<ASTNode>, Box<ASTNode>),
32    Sub(Box<ASTNode>, Box<ASTNode>),
33    Mul(Box<ASTNode>, Box<ASTNode>),
34    Div(Box<ASTNode>, Box<ASTNode>),
35    Exp(Box<ASTNode>, Box<ASTNode>),
36    FDiv(Box<ASTNode>, Box<ASTNode>),
37    Mod(Box<ASTNode>, Box<ASTNode>),
38
39    // LogicOps
40    And(Box<ASTNode>, Box<ASTNode>),
41    Or(Box<ASTNode>, Box<ASTNode>),
42
43    // RelationalOps
44    Lt(Box<ASTNode>, Box<ASTNode>),
45    Le(Box<ASTNode>, Box<ASTNode>),
46    Gt(Box<ASTNode>, Box<ASTNode>),
47    Ge(Box<ASTNode>, Box<ASTNode>),
48    Eq(Box<ASTNode>, Box<ASTNode>),
49    Ne(Box<ASTNode>, Box<ASTNode>),
50
51    // BinaryOps
52    BitOr(Box<ASTNode>, Box<ASTNode>),
53    BitAnd(Box<ASTNode>, Box<ASTNode>),
54    BitXor(Box<ASTNode>, Box<ASTNode>),
55    Rsh(Box<ASTNode>, Box<ASTNode>),
56    Lsh(Box<ASTNode>, Box<ASTNode>),
57
58    // UnaryOps
59    BinNot(Box<ASTNode>),
60    Not(Box<ASTNode>),
61    Len(Box<ASTNode>),
62    UMin(Box<ASTNode>),
63
64    // ConcatenationOps
65    Concat(Box<ASTNode>, Box<ASTNode>),
66
67    // Expression
68    /// Takes one of
69    /// Var
70    /// FunctionCall
71    /// Exp
72    PrefixExp(Box<ASTNode>),
73
74    Nil,
75    VarArg,
76    TableConstructor(Box<Option<ASTNode>>),
77
78    // Function
79    /// Takes a FunctionBody
80    Function(Box<ASTNode>),
81    /// Takes a ParameterList and a Block
82    FunctionBody(Box<Option<ASTNode>>, Box<ASTNode>),
83    /// Has 3 parameters
84    /// the example: log.ms:al
85    /// would produce
86    /// Name log
87    /// Name ms
88    /// Name al
89    FunctionName(Box<ASTNode>, Option<Vec<ASTNode>>, Option<Box<ASTNode>>),
90    /// Takes a Name and a FunctionBody
91    NamedFunction(Box<ASTNode>, Box<ASTNode>),
92
93    // Lists
94    ExpList(Vec<ASTNode>),
95    VarList(Vec<ASTNode>),
96    NameList(Vec<ASTNode>),
97    FieldList(Vec<ASTNode>),
98    /// Takes a list of parameters and is vararg
99    ParameterList(Box<Option<ASTNode>>, bool),
100
101    // Field
102    /// Contains an expr
103    FieldSingle(Box<ASTNode>),
104    /// The first node may be an expr to be resolved or a Name
105    /// The second node is the assigned expr
106    FieldAssign(Box<ASTNode>, Box<ASTNode>),
107
108    // Local
109    Local(Box<ASTNode>),
110
111    // Var
112    /// Takes a Name
113    Var(Box<ASTNode>),
114    /// Takes a prefixexp and a exp
115    VarPrefixed(Box<ASTNode>, Box<ASTNode>),
116    /// Takes a prefixexp and a Name
117    VarListAccess(Box<ASTNode>, Box<ASTNode>),
118}
119
120impl Debug for ASTNode {
121    fn fmt(&self, format: &mut Formatter) -> fmt::Result {
122        use self::ASTNode::*;
123        match *self {
124            Integer(val) => write!(format, "{}", val),
125            Float(val) => write!(format, "{}f", val),
126            Bool(val) => write!(format, "{}", val),
127            String(ref val) => write!(format, "\"{}\"", val),
128
129            /// Holds a lua name, usually a function or variable name
130            /// Contains `ASTNode::String`
131            Name(ref val) => write!(format, "(name {})", val),
132
133            /// Holds a lua label name
134            /// Contains `ASTNode::Name`
135            Label(ref val) => write!(format, "::{}::", val),
136            /// Contains an expression
137            Paren(ref expr) => write!(format, "({})", expr),
138
139            // Block
140            Block(ref statements, ref retstat) => {
141                write!(format, "(block\n");
142                for e in statements.iter() {
143                    write!(format, "\t{}\n", e);
144                }
145                if let Some(ref ret_ast) = **retstat {
146                    write!(format, "\treturn {}\n", ret_ast);
147                }
148                write!(format, ")")
149            }
150
151            // Statements
152            EmptyStatement => write!(format, "(statement)"),
153            RetStat(ref para) => write!(format, "(ret {:?})", para),
154            Break => write!(format, "(break)"),
155            Goto(ref loc) => write!(format, "goto {}", loc),
156
157            // ArithmeticOps
158            Add(ref left, ref right) => write!(format, "({} + {})", left, right),
159            Sub(ref left, ref right) => write!(format, "({} - {})", left, right),
160            Mul(ref left, ref right) => write!(format, "({} * {})", left, right),
161            Div(ref left, ref right) => write!(format, "({} / {})", left, right),
162            Exp(ref left, ref right) => write!(format, "({} ^ {})", left, right),
163            FDiv(ref left, ref right) => write!(format, "({} // {})", left, right),
164            Mod(ref left, ref right) => write!(format, "({} % {})", left, right),
165
166            // LogicOps
167            And(ref left, ref right) => write!(format, "({} and {})", left, right),
168            Or(ref left, ref right) => write!(format, "({} or {})", left, right),
169
170            // ArithmeticOps
171            Lt(ref left, ref right) => write!(format, "({} < {})", left, right),
172            Le(ref left, ref right) => write!(format, "({} <= {})", left, right),
173            Gt(ref left, ref right) => write!(format, "({} > {})", left, right),
174            Ge(ref left, ref right) => write!(format, "({} >= {})", left, right),
175            Eq(ref left, ref right) => write!(format, "({} == {})", left, right),
176            Ne(ref left, ref right) => write!(format, "({} ~= {})", left, right),
177
178            // BinaryOps
179            BitAnd(ref left, ref right) => write!(format, "({} & {})", left, right),
180            BitOr(ref left, ref right) => write!(format, "({} | {})", left, right),
181            BitXor(ref left, ref right) => write!(format, "({} ~ {})", left, right),
182            Rsh(ref left, ref right) => write!(format, "({} >> {})", left, right),
183            Lsh(ref left, ref right) => write!(format, "({} << {})", left, right),
184
185            // UnaryOps
186            BinNot(ref right) => write!(format, "~{}", right),
187            Len(ref right) => write!(format, "#{}", right),
188            UMin(ref right) => write!(format, "-{}", right),
189            Not(ref right) => write!(format, "not {}", right),
190
191            // ConcatenationOps
192            Concat(ref left, ref right) => write!(format, "{} .. {}", left, right),
193
194            // Exp
195            PrefixExp(ref e) => write!(format, "{}", e),
196
197            Nil => write!(format, "nil"),
198            VarArg => write!(format, "..."),
199            //TODO: Remove this debug impl
200            TableConstructor(ref fieldlist) => write!(format, "{{ {:?} }}", fieldlist),
201
202            // Function
203            Function(ref f) => write!(format, "{}", f),
204            FunctionBody(ref parlist, ref fbody) => write!(format, "function ({:?}) {}", parlist, fbody),
205            FunctionName(ref n, ref m, ref f) => write!(format, "{}.{:?}:{:?}", n, m, f),
206            NamedFunction(ref n, ref f) => write!(format, "(named {} {})", n, f),
207
208            // Lists
209            ExpList(ref explist) => {
210                write!(format, "(explist\n");
211                for e in explist.iter() {
212                    write!(format, "\t{}\n", e);
213                }
214                write!(format, ")")
215            },
216            VarList(ref varlist) => {
217                write!(format, "(varlist\n");
218                for e in varlist.iter() {
219                    write!(format, "\t{}\n", e);
220                }
221                write!(format, ")")
222            },
223            NameList(ref namelist) => {
224                write!(format, "(namelist\n");
225                for e in namelist.iter() {
226                    write!(format, "\t{}\n", e);
227                }
228                write!(format, ")")
229            },
230            ParameterList(ref plist, ref va) => {
231                write!(format, "(paramlist\n");
232                for e in plist.iter() {
233                    write!(format, "\t{}\n", e);
234                }
235                if *va {
236                    write!(format, "\t...\n");
237                }
238                write!(format, ")")
239            },
240            FieldList(ref fieldlist) => {
241                write!(format, "(fieldlist\n");
242                for e in fieldlist.iter() {
243                    write!(format, "\t{}\n", e);
244                }
245                write!(format, ")")
246            },
247
248            // Field
249            FieldSingle(ref e) => write!(format, "(field {})", e),
250            FieldAssign(ref n, ref e) => write!(format, "(field {} => {})", n, e),
251
252            //Local
253            Local(ref inner) => write!(format, "local {}", inner),
254
255            //Var
256            Var(ref name) => write!(format, "(var {})", name),
257            VarPrefixed(ref pe, ref e) => write!(format, "{}[{}]", pe, e),
258            VarListAccess(ref pe, ref n) => write!(format, "{}.{}", pe, n)
259        }
260    }
261
262}
263
264impl Display for ASTNode {
265    fn fmt(&self, format: &mut Formatter) -> fmt::Result {
266        use ASTNode::*;
267        match *self {
268            //TODO: Check if the DOT format supports ()
269            Integer(a) => write!(format, "Integer_{}_", a),
270            Float(a) => write!(format, "Float_{}_", a),
271            Bool(a) => write!(format, "Bool_{}_", a),
272            // Dot does not allow spaces and a bunch of things in the names
273            // we should change some of this stuff
274            String(ref a) => write!(format, "String_{}_", a),
275            Label(ref a) => write!(format, "Label_{}_", a),
276            Name(ref a) => write!(format, "Name_{}_", a),
277            Paren(_) => write!(format, "Paren"),
278            Block(_, _) => write!(format, "Block"),
279            EmptyStatement => write!(format, "EmptyStatement"),
280            Break => write!(format, "Break"),
281            Goto(_) => write!(format, "Goto"),
282            RetStat(_) => write!(format, "RetStat"),
283            Add(_, _) => write!(format, "Add"),
284            Sub(_, _) => write!(format, "Sub"),
285            Mul(_, _) => write!(format, "Mul"),
286            Div(_, _) => write!(format, "Div"),
287            Exp(_, _) => write!(format, "Exp"),
288            FDiv(_, _) => write!(format, "FDiv"),
289            Mod(_, _) => write!(format, "Mod"),
290            And(_, _) => write!(format, "And"),
291            Or(_, _) => write!(format, "Or"),
292            Lt(_, _) => write!(format, "Lt"),
293            Le(_, _) => write!(format, "Le"),
294            Gt(_, _) => write!(format, "Gt"),
295            Ge(_, _) => write!(format, "Ge"),
296            Eq(_, _) => write!(format, "Eq"),
297            Ne(_, _) => write!(format, "Ne"),
298            BitOr(_, _) => write!(format, "BitOr"),
299            BitAnd(_, _) => write!(format, "BitAnd"),
300            BitXor(_, _) => write!(format, "BitXor"),
301            Rsh(_, _) => write!(format, "Rsh"),
302            Lsh(_, _) => write!(format, "Lsh"),
303            BinNot(_) => write!(format, "BinNot"),
304            Not(_) => write!(format, "Not"),
305            Len(_) => write!(format, "Len"),
306            UMin(_) => write!(format, "UMin"),
307            Concat(_, _) => write!(format, "Concat"),
308            PrefixExp(_) => write!(format, "PrefixExp"),
309            Nil => write!(format, "Nil"),
310            VarArg => write!(format, "VarArg"),
311            TableConstructor(_) => write!(format, "TableConstructor"),
312            Function(_) => write!(format, "Function"),
313            FunctionBody(_, _) => write!(format, "FunctionBody"),
314            FunctionName(_, _, _) => write!(format, "FunctionName"),
315            NamedFunction(_, _) => write!(format, "NamedFunction"),
316            ExpList(_) => write!(format, "ExpList"),
317            VarList(_) => write!(format, "VarList"),
318            NameList(_) => write!(format, "NameList"),
319            FieldList(_) => write!(format, "FieldList"),
320            ParameterList(_, _) => write!(format, "ParameterList"),
321            FieldSingle(_) => write!(format, "FieldSingle"),
322            FieldAssign(_, _) => write!(format, "FieldAssign"),
323            Local(_) => write!(format, "Local"),
324            Var(_) => write!(format, "Var"),
325            VarPrefixed(_, _) => write!(format, "VarPrefixed"),
326            VarListAccess(_, _) => write!(format, "VarListAccess"),
327        }
328    }
329}
330
331//TODO: There is a bunch of cloing here that might not be necessary
332//TODO: Is there a better way to do this, or do we need 6 cfg blocks
333#[cfg(feature="graphviz")]
334type Node = ASTNode;
335#[cfg(feature="graphviz")]
336type Edge = (ASTNode, ASTNode);
337#[cfg(feature="graphviz")]
338struct Edges(Vec<Edge>);
339#[cfg(feature="graphviz")]
340use dot;
341#[cfg(feature="graphviz")]
342use std::borrow::Cow;
343#[cfg(feature="graphviz")]
344use std::io::Write;
345
346
347#[cfg(feature="graphviz")]
348impl<'a> dot::Labeller<'a, Node, Edge> for Edges {
349    fn graph_id(&'a self) -> dot::Id<'a> {
350        dot::Id::new("AST").unwrap()
351    }
352
353    fn node_id(&'a self, node: &Node) -> dot::Id<'a> {
354        dot::Id::new(format!("{}", node)).unwrap()
355    }
356}
357
358
359#[cfg(feature="graphviz")]
360impl<'a> dot::GraphWalk<'a, Node, Edge> for Edges {
361    fn nodes(&self) -> dot::Nodes<'a,Node> {
362        // (assumes that |N| \approxeq |E|)
363        let &Edges(ref v) = self;
364        let mut node_vec = Vec::with_capacity(v.len());
365        for n in v {
366            let &(ref s, ref t) = n;
367            node_vec.extend(s.sub_nodes());
368            node_vec.extend(t.sub_nodes());
369        }
370        node_vec.dedup();
371        Cow::Owned(node_vec)
372    }
373
374    fn edges(&'a self) -> dot::Edges<'a,Edge> {
375        let &Edges(ref edges) = self;
376        Cow::Borrowed(&edges[..])
377    }
378
379    fn source(&self, e: &Edge) -> Node { let &(ref s,_) = e; s.clone() }
380
381    fn target(&self, e: &Edge) -> Node { let &(_,ref t) = e; t.clone() }
382}
383
384
385#[cfg(feature="graphviz")]
386impl ASTNode {
387    fn generate_edges(&self) -> Vec<(ASTNode, ASTNode)> {
388        use ASTNode::*;
389        let mut node_vec = Vec::new();
390        match (*self).clone() {
391
392            Integer(_) |
393            Float(_) |
394            Bool(_) |
395            String(_) |
396            Label(_) |
397            Name(_) |
398            Nil |
399            Break |
400            VarArg |
401            EmptyStatement => {},
402
403            Paren(a) |
404            Local(a) |
405            Var(a) |
406            Goto(a) |
407            BinNot(a) |
408            Not(a) |
409            Len(a) |
410            UMin(a) |
411            PrefixExp(a) |
412            Function(a) |
413            FieldSingle(a) |
414            PrefixExp(a) => {
415                node_vec.push(((*self).clone(), (*a).clone()));
416                node_vec.extend(a.generate_edges());
417            },
418
419            Add(a, b) |
420            Sub(a, b) |
421            Mul(a, b) |
422            Div(a, b) |
423            Exp(a, b) |
424            FDiv(a, b) |
425            Mod(a, b) |
426            And(a, b) |
427            Or(a, b) |
428            Lt(a, b) |
429            Le(a, b) |
430            Gt(a, b) |
431            Ge(a, b) |
432            Eq(a, b) |
433            Ne(a, b) |
434            BitOr(a, b) |
435            BitAnd(a, b) |
436            BitXor(a, b) |
437            Rsh(a, b) |
438            Lsh(a, b) |
439            Concat(a, b) |
440            FieldAssign(a, b) |
441            VarPrefixed(a, b) |
442            VarListAccess(a, b) |
443            NamedFunction(a, b) => {
444                node_vec.push(((*self).clone(), (*a).clone()));
445                node_vec.push(((*self).clone(), (*b).clone()));
446                node_vec.extend(a.generate_edges());
447                node_vec.extend(b.generate_edges());
448            },
449
450            RetStat(a) |
451            TableConstructor(a) |
452            ParameterList(a, _) => if let Some(sa) = *a {
453                node_vec.push(((*self).clone(), sa.clone()));
454                node_vec.extend(sa.generate_edges());
455            },
456
457            ExpList(a) |
458            VarList(a) |
459            NameList(a) |
460            FieldList(a) => {
461                a.iter().map(|ae| {
462                    node_vec.push(((*self).clone(), (*ae).clone()));
463                    node_vec.extend(ae.generate_edges());
464                });
465            },
466
467            Block(a, b) => {
468                a.iter().map(|ae| {
469                    node_vec.push(((*self).clone(), (*ae).clone()));
470                    node_vec.extend(ae.generate_edges());
471                });
472                if let Some(sb) = *b {
473                    node_vec.push(((*self).clone(), sb.clone()));
474                    node_vec.extend(sb.generate_edges());
475                };
476            },
477            FunctionBody(a, b) => {
478                if let Some(sa) = *a {
479                    node_vec.push(((*self).clone(), sa.clone()));
480                    node_vec.extend(sa.generate_edges());
481                };
482                node_vec.push(((*self).clone(), (*b).clone()));
483                node_vec.extend(b.generate_edges());
484            },
485            FunctionName(a, b, c) => {
486                node_vec.push(((*self).clone(), (*a).clone()));
487                node_vec.extend(a.generate_edges());
488                if let Some(sb) = b {
489                    sb.iter().map(|sbe| {
490                        node_vec.push(((*self).clone(), (*sbe).clone()));
491                        node_vec.extend(sbe.generate_edges());
492                    });
493                };
494                if let Some(sc) = c {
495                    node_vec.push(((*self).clone(), (*sc).clone()));
496                    node_vec.extend(sc.generate_edges());
497                };
498            },
499            _ => panic!("Unimplemented: GenEdges"),
500        }
501        node_vec
502    }
503
504    fn sub_nodes(&self) -> Vec<ASTNode> {
505        use ASTNode::*;
506        let mut node_vec = Vec::new();
507
508        node_vec.push((*self).clone());
509
510        match (*self).clone() {
511            Nil |
512            VarArg |
513            Break |
514            EmptyStatement |
515            Float(_) |
516            Bool(_) |
517            String(_) |
518            Label(_) |
519            Name(_) |
520            Integer(_) => {},
521
522            Goto(a) |
523            BinNot(a) |
524            Not(a) |
525            Len(a) |
526            UMin(a) |
527            PrefixExp(a) |
528            FieldSingle(a) |
529            Local(a) |
530            Var(a) |
531            Function(a) |
532            PrefixExp(a) |
533            Paren(a) => node_vec.extend(a.sub_nodes()),
534
535            And(a, b) |
536            Or(a, b) |
537            Lt(a, b) |
538            Le(a, b) |
539            Gt(a, b) |
540            Ge(a, b) |
541            Eq(a, b) |
542            Ne(a, b) |
543            BitOr(a, b) |
544            BitAnd(a, b) |
545            BitXor(a, b) |
546            Rsh(a, b) |
547            Lsh(a, b) |
548            FieldAssign(a, b) |
549            VarPrefixed(a, b) |
550            VarListAccess(a, b) |
551            NamedFunction(a, b) |
552            Concat(a, b) |
553            Add(a, b) |
554            Sub(a, b) |
555            Mul(a, b) |
556            Div(a, b) |
557            Exp(a, b) |
558            FDiv(a, b) |
559            Mod(a, b) => {
560                node_vec.extend(a.sub_nodes());
561                node_vec.extend(b.sub_nodes());
562            },
563
564            ExpList(a) |
565            VarList(a) |
566            NameList(a) |
567            FieldList(a) => { a.iter().map(|b| node_vec.extend(b.sub_nodes())); },
568
569            RetStat(a) |
570            ParameterList(a, _) |
571            TableConstructor(a) => if let Some(sa) = *a {
572                node_vec.extend(sa.sub_nodes());
573            },
574
575            Block(a, b) => {
576                a.iter().map(|ae| node_vec.extend(ae.sub_nodes()));
577                if let Some(sb) = *b {
578                    node_vec.extend(sb.sub_nodes());
579                }
580            },
581
582            FunctionBody(a, b) => {
583                if let Some(sa) = *a {
584                    node_vec.extend(sa.sub_nodes());
585                }
586                node_vec.extend(b.sub_nodes());
587            },
588
589            FunctionName(a, b, c) => {
590                node_vec.extend(a.sub_nodes());
591                if let Some(sb) = b {
592                    sb.iter().map(|sbe| node_vec.extend(sbe.sub_nodes()));
593                };
594                if let Some(sc) = c {
595                    node_vec.extend(sc.sub_nodes());
596                }
597            },
598            _ => panic!("Unimplemented: SubNodes"),
599        };
600        node_vec
601    }
602
603    #[cfg(feature="graphviz")]
604    pub fn graphviz_render<W: Write>(&self, output: &mut W) {
605        let edges = Edges(self.generate_edges());
606        dot::render(&edges, output).unwrap()
607    }
608}