Skip to content

Commit

Permalink
parser(feat): add struct reference
Browse files Browse the repository at this point in the history
  • Loading branch information
chanbengz committed Dec 7, 2024
1 parent e1c97bb commit e71882f
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 35 deletions.
10 changes: 6 additions & 4 deletions src/ast/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ impl fmt::Display for Variable {
ident,
value,
dims.iter().map(|d| d.to_string()).collect::<Vec<String>>().join(", ")),
Variable::MemberReference(ident, member) => write!(f, "{}.{}", ident, member),
Variable::MemberReference(refs) => write!(f, "Member Reference: [{}]",
refs.iter().map(|(ident, field, dims)| format!("{}.{}{}", ident, field,
dims.iter().map(|d| format!("[{}]", d)).collect::<Vec<String>>().join(""))).collect::<Vec<String>>().join(", ")
),
Variable::FormalParameter(ident, value, dims) => write!(f, "Formal Parameter: {} = [{}] with dimensions [{}]",
ident,
value,
Expand All @@ -47,15 +50,14 @@ impl fmt::Display for Variable {
dims.iter().map(|d| format!("[{}]", d)).collect::<Vec<String>>().join("")),
Variable::VarAssignment(ident, expr, dims) => write!(f, "Variable Assignment: {}{} = {}", ident,
dims.iter().map(|d| format!("[{}]", d)).collect::<Vec<String>>().join(""), expr),
Variable::StructReference(ident) => write!(f, "Struct Reference: {}", ident),
Variable::StructDefinition(ident, vars) => write!(f, "Struct Definition: {} with [{}]",
Variable::StructDefinition(ident, vars) => write!(f, "Struct Definition: {} with [{}]",
ident,
vars.iter().map(|v| format!("{}", v)).collect::<Vec<String>>().join(", ")),
Variable::StructDeclaration(ident, parent, vars) => write!(f, "Struct Declaration: {} extends {} with [{}]",
ident,
parent,
vars.iter().map(|v| format!("{}", v)).collect::<Vec<String>>().join(", ")),
Variable::StructAssignment(ident, field, expr) => write!(f, "Struct Assignment: {}.{} = {}", ident, field, expr),
Variable::StructAssignment(var, expr) => write!(f, "Struct Assignment: {} = {}", var, expr),

Variable::Error => write!(f, "[VariableError]")
}
Expand Down
5 changes: 2 additions & 3 deletions src/ast/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,13 @@ pub enum Variable {
VarAssignment(Box<String>, Box<CompExpr>, Box<Vec<CompExpr>>), // varname, expr, offsets

// Struct is defined to realize object.
StructReference(Box<String>),
StructDefinition(Box<String>, Box<Vec<Variable>>),
// Object type, Identifier, Variables
StructDeclaration(Box<String>, Box<String>, Box<Vec<Variable>>),
// Identifier, Field, Variable
StructAssignment(Box<String>, Box<String>, Box<CompExpr>),
StructAssignment(Box<Variable>, Box<CompExpr>),

MemberReference(Box<String>, Box<String>),
MemberReference(Vec<(Box<String>, Box<String>, Box<Vec<CompExpr>>)>),
FormalParameter(Box<String>, Box<Value>, Box<Vec<usize>>),
Error
}
Expand Down
78 changes: 52 additions & 26 deletions src/parser/src/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,51 @@ ForExpr: tree::Expr = {
},
}

StructRef: Vec<(Box<String>, Box<String>, Box<Vec<tree::CompExpr>>)> = {
<mut v:StructRef> "." <l:@L> <field:Identifier?> <r:@R> <dims:DimDecs?> => {
if field == None {
let error = ErrorRecovery {
error: ParseError::User {
error: LexicalError::MissingLexeme(Span {
source: source.to_string(),
start: l - 1,
end: l
}, "field name".to_string())
},
dropped_tokens: Vec::new(),
};
errors.push(error);
return Vec::new();
}
let last = v.last().unwrap().clone();
v.push((
Box::new((*last.1).clone()),
Box::new(field.unwrap()),
Box::new(dims.unwrap_or(Vec::new()))
));
v
},
<parent:Identifier> "." <l:@L> <field:Identifier?> <r:@R> => {
if field == None {
let error = ErrorRecovery {
error: ParseError::User {
error: LexicalError::MissingLexeme(Span {
source: source.to_string(),
start: l - 1,
end: l
}, "field name".to_string())
},
dropped_tokens: Vec::new(),
};
errors.push(error);
return Vec::new();
}
let mut v = Vec::new();
v.push((Box::new(parent), Box::new(field.unwrap()), Box::new(Vec::new())));
v
},
}

VarManagement: tree::Expr = {
/* Four types of assignment:
* 1. Variable declaration: Specifier VarDecs;
Expand All @@ -614,25 +659,11 @@ VarManagement: tree::Expr = {
vec![def]
)
},
<obj: Identifier> "." <l:@L> <field: Identifier?> <r:@R> "=" <val:CompExpr> => {
if field == None {
let error = ErrorRecovery {
error: ParseError::User {
error: LexicalError::MissingLexeme(Span {
source: source.to_string(),
start: l - 1,
end: l
}, "field name".to_string())
},
dropped_tokens: Vec::new(),
};
errors.push(error);
return tree::Expr::Error;
}
<s:StructRef> "=" <val:CompExpr> => {
let s = Box::new(tree::Variable::MemberReference(s));
tree::Expr::VarManagement(
vec![tree::Variable::StructAssignment(
Box::new(obj),
Box::new(field.unwrap()),
s,
val
)]
)
Expand Down Expand Up @@ -1025,13 +1056,9 @@ Term: Box<tree::CompExpr> = {
tree::Function::FuncReference(Box::new(ident), args)
))
},
<obj:Identifier> "." <field:Identifier> => {
Box::new(tree::CompExpr::Variable(
tree::Variable::MemberReference(
Box::new(obj),
Box::new(field)
)
))

<s:StructRef> => {
Box::new(tree::CompExpr::Variable(tree::Variable::MemberReference(s)))
},

// error recovery
Expand Down Expand Up @@ -1077,7 +1104,6 @@ Term: Box<tree::CompExpr> = {
errors.push(error);
Box::new(tree::CompExpr::Invalid)
},

}

CondTerm: Box<tree::CondExpr> = {
Expand Down Expand Up @@ -1167,4 +1193,4 @@ extern {
"invalid" => Token::Invalid,
"error" => Token::Error,
}
}
}
2 changes: 1 addition & 1 deletion src/parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ mod tests {
&format!("../test/phase1/basic/test_1_r{:0>2}.out", i)
);
}
for i in 1..14 {
for i in 1..12 {
assert_parse_from_file(Parser::ProgramParser,
&format!("../test/phase1/extra/test_1_s{:0>2}.spl", i),
&format!("../test/phase1/extra/test_1_s{:0>2}.out", i)
Expand Down
2 changes: 1 addition & 1 deletion src/test/phase1/basic/test_1_r02.out
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Statement: GlobalVariable: [Variable Declaration: global = [0: u32] with dimensions []], Statement: Struct: Struct Definition: my_struct with [Variable Declaration: code = [0: u32] with dimensions [], Variable Declaration: data = [ : char] with dimensions []], Functions: Function: test_1_r02:[Body: [Struct Declaration: my_struct extends obj with [], Struct Assignment: obj.code = global, Variable Assignment: global = (global + 1: u32)]]
Statement: GlobalVariable: [Variable Declaration: global = [0: u32] with dimensions []], Statement: Struct: Struct Definition: my_struct with [Variable Declaration: code = [0: u32] with dimensions [], Variable Declaration: data = [ : char] with dimensions []], Functions: Function: test_1_r02:[Body: [Struct Declaration: my_struct extends obj with [], Struct Assignment: Member Reference: [obj.code] = global, Variable Assignment: global = (global + 1: u32)]]

0 comments on commit e71882f

Please sign in to comment.