Skip to content

Commit eceea01

Browse files
committed
Demo visitor with return value
Require rrevenantt/antlr4rust#29
1 parent 90b2931 commit eceea01

File tree

4 files changed

+131
-4
lines changed

4 files changed

+131
-4
lines changed

antlr-calc/src/calc_parser_v3.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
use antlr_rust::tree::{ParseTree, ParseTreeVisitorCompat, Visitable};
2+
use antlr_rust::InputStream;
3+
use antlr_rust::{common_token_stream::CommonTokenStream, token_factory::CommonTokenFactory};
4+
use serde::{Deserialize, Serialize};
5+
use std::collections::HashMap;
6+
7+
use crate::{AddSubContext, AddSubContextAttrs, MulDivContextAttrs, PrintExprContextAttrs};
8+
9+
use crate::{
10+
AssignContext, IdContext, IntContext, LabeledExprLexer, LabeledExprParser,
11+
LabeledExprParserContextType, LabeledExprVisitorCompat, MulDivContext,
12+
};
13+
14+
use crate::PrintExprContext;
15+
16+
use crate::grammar::labeledexprparser::AssignContextAttrs;
17+
18+
#[derive(Serialize, Deserialize, Debug, Clone)]
19+
pub struct Calc3 {
20+
pub memory: HashMap<String, i64>,
21+
pub res: i64,
22+
}
23+
24+
impl Default for Calc3 {
25+
fn default() -> Self {
26+
Calc3 {
27+
memory: HashMap::new(),
28+
res: 0,
29+
}
30+
}
31+
}
32+
33+
pub struct CalcParser {
34+
pub(crate) calc: Calc3,
35+
}
36+
37+
pub fn str_to_calc_v3<'input>(data: &str) -> Calc3 {
38+
let tf = CommonTokenFactory::default();
39+
let lexer = LabeledExprLexer::new_with_token_factory(InputStream::new(data.into()), &tf);
40+
let token_source = CommonTokenStream::new(lexer);
41+
let mut parser = LabeledExprParser::new(token_source);
42+
let result = parser.prog().expect("parsed unsuccessfully");
43+
44+
let mut calc_parser = CalcParser {
45+
calc: Default::default(),
46+
};
47+
48+
result.accept(&mut calc_parser);
49+
50+
calc_parser.calc
51+
}
52+
53+
impl ParseTreeVisitorCompat<'_> for CalcParser {
54+
type Node = LabeledExprParserContextType;
55+
type Return = i64;
56+
57+
fn temp_result(&mut self) -> &mut Self::Return {
58+
&mut self.calc.res
59+
}
60+
61+
fn aggregate_results(&self, aggregate: Self::Return, next: Self::Return) -> Self::Return {
62+
aggregate + &next
63+
}
64+
}
65+
66+
impl LabeledExprVisitorCompat<'_> for CalcParser {
67+
fn visit_printExpr(&mut self, ctx: &PrintExprContext) -> Self::Return {
68+
let value = ctx.get_text();
69+
let res = self.visit(&*ctx.expr().unwrap());
70+
println!("{} = {:?}", value, res);
71+
self.calc.res
72+
}
73+
74+
fn visit_assign(&mut self, ctx: &AssignContext) -> Self::Return {
75+
let id = ctx.ID().unwrap();
76+
let value = ctx.expr().unwrap().get_text();
77+
println!("{:?} = {}", id, value);
78+
self.visit(&*ctx.expr().unwrap());
79+
let v = if self.calc.memory.get(&value).is_none() {
80+
value.parse().unwrap()
81+
} else {
82+
*self.calc.memory.get(&value).unwrap()
83+
};
84+
self.calc.memory.insert(id.get_text(), v);
85+
v
86+
}
87+
88+
fn visit_MulDiv(&mut self, ctx: &MulDivContext) -> Self::Return {
89+
let left = self.visit(&*ctx.expr(0).unwrap());
90+
let right = self.visit(&*ctx.expr(1).unwrap());
91+
if ctx.MUL().is_some() {
92+
left * right
93+
} else {
94+
left / right
95+
}
96+
}
97+
98+
fn visit_AddSub(&mut self, ctx: &AddSubContext) -> Self::Return {
99+
let left = self.visit(&*ctx.expr(0).unwrap());
100+
let right = self.visit(&*ctx.expr(1).unwrap());
101+
if ctx.ADD().is_some() {
102+
left + right
103+
} else {
104+
left - right
105+
}
106+
}
107+
108+
fn visit_id(&mut self, ctx: &IdContext) -> Self::Return {
109+
let value = ctx.get_text();
110+
if self.calc.memory.get(&value).is_none() {
111+
0
112+
} else {
113+
*self.calc.memory.get(&value).unwrap()
114+
}
115+
}
116+
117+
fn visit_int(&mut self, ctx: &IntContext) -> Self::Return {
118+
ctx.get_text().parse().unwrap()
119+
}
120+
}

antlr-calc/src/grammar/labeledexprvisitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Generated from LabeledExpr.g4 by ANTLR 4.8
33
use antlr_rust::tree::{ParseTreeVisitor,ParseTreeVisitorCompat};
44
use super::labeledexprparser::*;
5-
use std::mem;
5+
66

77
/**
88
* This interface defines a complete generic visitor for a parse tree produced

antlr-calc/src/lib.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
#![feature(try_blocks)]
22

3-
pub use calc_parser::*;
3+
pub use calc_parser::str_to_calc;
4+
5+
pub use calc_parser_v3::str_to_calc_v3;
6+
use calc_parser_v3::Calc3;
47
pub use grammar::*;
58

69
pub mod calc_parser;
10+
pub mod calc_parser_v3;
711
pub mod grammar;
812

9-
pub fn parse(str: &str) -> Calc {
10-
str_to_calc(str)
13+
pub fn parse(str: &str) -> Calc3 {
14+
str_to_calc_v3(str)
1115
}
1216

1317
#[cfg(test)]

antlr-calc/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use antlr_calc::str_to_calc;
2+
use antlr_calc::str_to_calc_v3;
23

34
fn main() {
45
let data = r#"
@@ -14,4 +15,6 @@ fn main() {
1415

1516
let result = str_to_calc(data);
1617
println!("{:?}", result);
18+
let result = str_to_calc_v3(data);
19+
println!("{:?}", result);
1720
}

0 commit comments

Comments
 (0)