Skip to content

Commit cd92cca

Browse files
authored
feat(ast): Introduce ParenExpression (#995)
1 parent d359949 commit cd92cca

File tree

28 files changed

+569
-252
lines changed

28 files changed

+569
-252
lines changed

.vscode/launch.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{
88
"type": "lldb",
99
"request": "launch",
10-
"name": "Debug source 'demo.st'",
10+
"name": "Debug source 'target/demo.st'",
1111
"cargo": {
1212
"args": [
1313
"build",

compiler/plc_ast/src/ast.rs

+28-15
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ pub struct AstNode {
584584
pub location: SourceLocation,
585585
}
586586

587-
#[derive(Clone, PartialEq)]
587+
#[derive(Debug, Clone, PartialEq)]
588588
pub enum AstStatement {
589589
EmptyStatement(EmptyStatement),
590590
// a placeholder that indicates a default value of a datatype
@@ -601,6 +601,7 @@ pub enum AstStatement {
601601
BinaryExpression(BinaryExpression),
602602
UnaryExpression(UnaryExpression),
603603
ExpressionList(Vec<AstNode>),
604+
ParenExpression(Box<AstNode>),
604605
RangeStatement(RangeStatement),
605606
VlaRangeStatement,
606607
// Assignment
@@ -639,6 +640,9 @@ impl Debug for AstNode {
639640
AstStatement::ExpressionList(expressions) => {
640641
f.debug_struct("ExpressionList").field("expressions", expressions).finish()
641642
}
643+
AstStatement::ParenExpression(expression) => {
644+
f.debug_struct("ParenExpression").field("expression", expression).finish()
645+
}
642646
AstStatement::RangeStatement(RangeStatement { start, end }) => {
643647
f.debug_struct("RangeStatement").field("start", start).field("end", end).finish()
644648
}
@@ -860,6 +864,10 @@ impl AstNode {
860864
)
861865
}
862866

867+
pub fn is_paren(&self) -> bool {
868+
matches!(self.stmt, AstStatement::ParenExpression { .. })
869+
}
870+
863871
pub fn is_expression_list(&self) -> bool {
864872
matches!(self.stmt, AstStatement::ExpressionList { .. })
865873
}
@@ -1012,6 +1020,7 @@ pub fn flatten_expression_list(list: &AstNode) -> Vec<&AstNode> {
10121020
AstStatement::MultipliedStatement(MultipliedStatement { multiplier, element }, ..) => {
10131021
std::iter::repeat(flatten_expression_list(element)).take(*multiplier as usize).flatten().collect()
10141022
}
1023+
AstStatement::ParenExpression(expression) => flatten_expression_list(expression),
10151024
_ => vec![list],
10161025
}
10171026
}
@@ -1133,6 +1142,10 @@ impl AstFactory {
11331142
AstNode { stmt: AstStatement::ExpressionList(expressions), location, id }
11341143
}
11351144

1145+
pub fn create_paren_expression(expression: AstNode, location: SourceLocation, id: AstId) -> AstNode {
1146+
AstNode { stmt: AstStatement::ParenExpression(Box::new(expression)), location, id }
1147+
}
1148+
11361149
/// creates a new if-statement
11371150
pub fn create_if_statement(
11381151
blocks: Vec<ConditionalBlock>,
@@ -1500,75 +1513,75 @@ impl AstFactory {
15001513
AstNode { stmt: AstStatement::LabelStatement(LabelStatement { name }), location, id }
15011514
}
15021515
}
1503-
#[derive(Clone, PartialEq)]
1516+
#[derive(Debug, Clone, PartialEq)]
15041517
pub struct EmptyStatement {}
15051518

1506-
#[derive(Clone, PartialEq)]
1519+
#[derive(Debug, Clone, PartialEq)]
15071520
pub struct DefaultValue {}
15081521

1509-
#[derive(Clone, PartialEq)]
1522+
#[derive(Debug, Clone, PartialEq)]
15101523
pub struct CastStatement {
15111524
pub target: Box<AstNode>,
15121525
pub type_name: String,
15131526
}
15141527

1515-
#[derive(Clone, PartialEq)]
1528+
#[derive(Debug, Clone, PartialEq)]
15161529
pub struct MultipliedStatement {
15171530
pub multiplier: u32,
15181531
pub element: Box<AstNode>,
15191532
}
1520-
#[derive(Clone, PartialEq)]
1533+
#[derive(Debug, Clone, PartialEq)]
15211534
pub struct ReferenceExpr {
15221535
pub access: ReferenceAccess,
15231536
pub base: Option<Box<AstNode>>,
15241537
}
15251538

1526-
#[derive(Clone, PartialEq)]
1539+
#[derive(Debug, Clone, PartialEq)]
15271540
pub struct DirectAccess {
15281541
pub access: DirectAccessType,
15291542
pub index: Box<AstNode>,
15301543
}
15311544

1532-
#[derive(Clone, PartialEq)]
1545+
#[derive(Debug, Clone, PartialEq)]
15331546
pub struct HardwareAccess {
15341547
pub direction: HardwareAccessType,
15351548
pub access: DirectAccessType,
15361549
pub address: Vec<AstNode>,
15371550
}
15381551

1539-
#[derive(Clone, PartialEq)]
1552+
#[derive(Debug, Clone, PartialEq)]
15401553
pub struct BinaryExpression {
15411554
pub operator: Operator,
15421555
pub left: Box<AstNode>,
15431556
pub right: Box<AstNode>,
15441557
}
15451558

1546-
#[derive(Clone, PartialEq)]
1559+
#[derive(Debug, Clone, PartialEq)]
15471560
pub struct UnaryExpression {
15481561
pub operator: Operator,
15491562
pub value: Box<AstNode>,
15501563
}
15511564

1552-
#[derive(Clone, PartialEq)]
1565+
#[derive(Debug, Clone, PartialEq)]
15531566
pub struct RangeStatement {
15541567
pub start: Box<AstNode>,
15551568
pub end: Box<AstNode>,
15561569
}
15571570

1558-
#[derive(Clone, PartialEq)]
1571+
#[derive(Debug, Clone, PartialEq)]
15591572
pub struct Assignment {
15601573
pub left: Box<AstNode>,
15611574
pub right: Box<AstNode>,
15621575
}
15631576

1564-
#[derive(Clone, PartialEq)]
1577+
#[derive(Debug, Clone, PartialEq)]
15651578
pub struct CallStatement {
15661579
pub operator: Box<AstNode>,
15671580
pub parameters: Option<Box<AstNode>>,
15681581
}
15691582

15701583
/// Represents a conditional jump from current location to a specified label
1571-
#[derive(Clone, Debug, PartialEq)]
1584+
#[derive(Debug, Clone, PartialEq)]
15721585
pub struct JumpStatement {
15731586
/// The condition based on which the current statement will perform a jump
15741587
pub condition: Box<AstNode>,
@@ -1577,7 +1590,7 @@ pub struct JumpStatement {
15771590
}
15781591

15791592
/// Represents a location in code that could be jumbed to
1580-
#[derive(Clone, Debug, PartialEq)]
1593+
#[derive(Debug, Clone, PartialEq)]
15811594
pub struct LabelStatement {
15821595
pub name: String,
15831596
}
+8-17
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
use std::fmt::{Debug, Formatter};
1+
use std::fmt::Debug;
22

33
use crate::ast::AstNode;
44

5-
#[derive(Clone, PartialEq)]
5+
#[derive(Debug, Clone, PartialEq)]
66
pub struct IfStatement {
77
pub blocks: Vec<ConditionalBlock>,
88
pub else_block: Vec<AstNode>,
99
}
1010

11-
#[derive(Clone, PartialEq)]
11+
#[derive(Debug, Clone, PartialEq)]
1212
pub struct ForLoopStatement {
1313
pub counter: Box<AstNode>,
1414
pub start: Box<AstNode>,
@@ -17,21 +17,21 @@ pub struct ForLoopStatement {
1717
pub body: Vec<AstNode>,
1818
}
1919

20-
#[derive(Clone, PartialEq)]
20+
#[derive(Debug, Clone, PartialEq)]
2121
/// used for While and Repeat loops
2222
pub struct LoopStatement {
2323
pub condition: Box<AstNode>,
2424
pub body: Vec<AstNode>,
2525
}
2626

27-
#[derive(Clone, PartialEq)]
27+
#[derive(Debug, Clone, PartialEq)]
2828
pub struct CaseStatement {
2929
pub selector: Box<AstNode>,
3030
pub case_blocks: Vec<ConditionalBlock>,
3131
pub else_block: Vec<AstNode>,
3232
}
3333

34-
#[derive(Clone, PartialEq)]
34+
#[derive(Debug, Clone, PartialEq)]
3535
pub enum AstControlStatement {
3636
If(IfStatement),
3737
ForLoop(ForLoopStatement),
@@ -40,24 +40,15 @@ pub enum AstControlStatement {
4040
Case(CaseStatement),
4141
}
4242

43-
#[derive(Clone, PartialEq)]
43+
#[derive(Debug, Clone, PartialEq)]
4444
pub struct ConditionalBlock {
4545
pub condition: Box<AstNode>,
4646
pub body: Vec<AstNode>,
4747
}
4848

49-
#[derive(Clone, PartialEq)]
49+
#[derive(Debug, Clone, PartialEq)]
5050
pub struct ReturnStatement {
5151
/// Indicates that the given condition must evaluate to true in order for the return to take place.
5252
/// Only used in CFC where the condition may be [`Some`] and [`None`] otherwise.
5353
pub condition: Option<Box<AstNode>>,
5454
}
55-
56-
impl Debug for ConditionalBlock {
57-
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
58-
f.debug_struct("ConditionalBlock")
59-
.field("condition", &self.condition)
60-
.field("body", &self.body)
61-
.finish()
62-
}
63-
}

compiler/plc_source/src/source_location.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl SourceLocationFactory {
5656
pub struct TextLocation {
5757
/// Line in the source code where this location points to
5858
line: usize,
59-
/// Column in the sourcecode where this location points o
59+
/// Column in the sourcecode where this location points to
6060
column: usize,
6161
/// Raw offset to this location from the start of the file
6262
offset: usize,

src/codegen/generators/expression_generator.rs

+1
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
237237
AstStatement::HardwareAccess { .. } => {
238238
Ok(ExpressionValue::RValue(self.llvm.i32_type().const_zero().into()))
239239
}
240+
AstStatement::ParenExpression(expr) => self.generate_expression_value(expr),
240241
//fallback
241242
_ => self.generate_literal(expression),
242243
}

src/lexer.rs

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ impl<'a> ParseSession<'a> {
114114
}
115115

116116
pub fn advance(&mut self) {
117+
log::trace!("{}", self.slice());
117118
self.last_range = self.range();
118119
self.last_token = std::mem::replace(&mut self.token, self.lexer.next().unwrap_or(Token::End));
119120
self.parse_progress += 1;

src/parser/expressions_parser.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,11 @@ fn parse_atomic_leaf_expression(lexer: &mut ParseSession<'_>) -> Result<AstNode,
257257
KeywordParensOpen => {
258258
parse_any_in_region(lexer, vec![KeywordParensClose], |lexer| {
259259
lexer.advance(); // eat KeywordParensOpen
260-
Ok(parse_expression(lexer))
260+
261+
let start = lexer.last_location();
262+
let expr = parse_expression(lexer);
263+
264+
Ok(AstFactory::create_paren_expression(expr, start.span(&lexer.location()), lexer.next_id()))
261265
})
262266
}
263267
Identifier => Ok(parse_identifier(lexer)),

src/parser/tests/expressions_parser_tests.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
use crate::parser::tests::ref_to;
33
use crate::test_utils::tests::parse;
44
use insta::{assert_debug_snapshot, assert_snapshot};
5-
use plc_ast::ast::{AstFactory, AstNode, DataType, DataTypeDeclaration, LinkageType, Operator, Pou, PouType};
5+
use plc_ast::ast::{
6+
AstFactory, AstNode, AstStatement, DataType, DataTypeDeclaration, LinkageType, Operator, Pou, PouType,
7+
};
68
use plc_ast::literals::AstLiteral;
79
use plc_source::source_location::SourceLocation;
810
use pretty_assertions::*;
@@ -145,7 +147,7 @@ fn additon_of_three_variables_parsed() {
145147
}
146148

147149
#[test]
148-
fn parenthesis_expressions_should_not_change_the_ast() {
150+
fn parenthesis_expressions_should_change_the_ast() {
149151
let src = "PROGRAM exp (x+y); END_PROGRAM";
150152
let result = parse(src).0;
151153

@@ -1765,3 +1767,13 @@ fn direct_access_as_expression_parsed() {
17651767
//THEN the AST contains direct address nodes at the access location
17661768
assert_debug_snapshot!(result);
17671769
}
1770+
1771+
#[test]
1772+
fn parenthesized_expression_span() {
1773+
let src = "PROGRAM prg [(1 + 2)] END_PROGRAM";
1774+
1775+
let (result, _) = parse(src);
1776+
let AstStatement::Literal(AstLiteral::Array(array)) = result.implementations[0].statements[0].get_stmt() else { panic!() };
1777+
let range = array.elements().unwrap().get_location().get_span().to_range().unwrap();
1778+
assert_eq!(&src[range.start..range.end], "(1 + 2)");
1779+
}

src/parser/tests/initializer_parser_tests.rs

+16
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,22 @@ fn struct_initializer_can_be_parsed() {
300300
assert_debug_snapshot!(x);
301301
}
302302

303+
#[test]
304+
fn parenthesized_expression_within_array() {
305+
let (result, _) = parse(
306+
"
307+
PROGRAM main
308+
VAR
309+
arr : ARRAY[1..5] OF DINT := [(1, 2, 3, 4, 5)];
310+
END_VAR
311+
END_PROGRAM
312+
",
313+
);
314+
315+
let member = &result.units[0].variable_blocks[0].variables[0];
316+
assert_debug_snapshot!(&member.initializer);
317+
}
318+
303319
#[test]
304320
fn array_initializer_in_pou_can_be_parsed() {
305321
let (result, ..) = parse(

0 commit comments

Comments
 (0)