mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
parse hello world
This commit is contained in:
parent
727cfc692c
commit
f229dd7fdc
7 changed files with 239 additions and 29 deletions
|
|
@ -78,11 +78,27 @@ pub struct ExprBinary {
|
|||
pub op: BinaryOp,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub enum PostfixOp {
|
||||
Call(Vec<Spanned<Expr>>),
|
||||
Member(Ident),
|
||||
ArrowMember(Ident),
|
||||
Increment,
|
||||
Decrement,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub struct ExprPostfix {
|
||||
pub lhs: Box<Spanned<Expr>>,
|
||||
pub op: PostfixOp,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub enum Expr {
|
||||
Atom(Atom),
|
||||
Unary(ExprUnary),
|
||||
Binary(ExprBinary),
|
||||
Postfix(ExprPostfix),
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -92,7 +108,10 @@ pub enum Expr {
|
|||
#[derive(Debug, DebugPls)]
|
||||
pub enum Stmt {
|
||||
Decl(Decl),
|
||||
Labeled{label: Ident, stmt: Box<Spanned<Stmt>>},
|
||||
Labeled {
|
||||
label: Ident,
|
||||
stmt: Box<Spanned<Stmt>>,
|
||||
},
|
||||
Compound(Vec<Spanned<Stmt>>),
|
||||
If {
|
||||
cond: Expr,
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ where
|
|||
/// (6.7) declaration:
|
||||
/// declaration-specifiers init-declarator-list.opt ;
|
||||
/// static_assert-declaration
|
||||
///
|
||||
///
|
||||
/// This does NOT eat the semicolon!
|
||||
fn declaration(&mut self) -> Result<Spanned<Decl>> {
|
||||
if let Some((tok, span)) = eat!(self, Tok::Kw(Kw::StaticAssert)) {
|
||||
|
|
@ -201,7 +201,7 @@ where
|
|||
/// init-declarator:
|
||||
/// declarator
|
||||
/// declarator = initializer
|
||||
///
|
||||
///
|
||||
fn init_declarator_list(&mut self) -> Result<Vec<Spanned<InitDecl>>> {
|
||||
let mut init_decls = Vec::new();
|
||||
let mut first = true;
|
||||
|
|
@ -477,7 +477,11 @@ where
|
|||
let span2 = expect!(self, Tok::Punct(P::Semicolon));
|
||||
return Ok((Stmt::Decl(decl), span.extend(span2)));
|
||||
}
|
||||
todo!()
|
||||
// all other stmts are indicated by keywords ...
|
||||
|
||||
// it must be an expression stmt
|
||||
let (expr, span) = self.expr()?;
|
||||
Ok((Stmt::Expr(expr), span))
|
||||
}
|
||||
|
||||
/// (6.8.2) compound-statement:
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
//! For more information, see https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
|
||||
|
||||
use crate::{
|
||||
ast::{ArithOpKind, Atom, BinaryOp, ComparisonKind, Expr, ExprBinary, ExprUnary, UnaryOp},
|
||||
parser::{expect, Parser, ParserError, Result},
|
||||
ast::{
|
||||
ArithOpKind, Atom, BinaryOp, ComparisonKind, Expr, ExprBinary, ExprPostfix, ExprUnary,
|
||||
PostfixOp, UnaryOp,
|
||||
},
|
||||
parser::{expect, Parser, ParserError, Result, eat},
|
||||
pre::Punctuator as P,
|
||||
token::{Constant, Token as Tok},
|
||||
Span, Spanned,
|
||||
|
|
@ -33,7 +36,9 @@ where
|
|||
return lhs;
|
||||
}
|
||||
&(Tok::Punct(punct), span) => {
|
||||
let r_bp = prefix_binding_power(&Tok::Punct(punct));
|
||||
let r_bp = prefix_binding_power(&Tok::Punct(punct)).ok_or_else(|| {
|
||||
ParserError::new(span, format!("expected expression, found {punct}"))
|
||||
})?;
|
||||
let Some(op) = unary_op_from_token(&Tok::Punct(punct)) else { panic!() };
|
||||
let rhs = self.expr_bp(r_bp)?;
|
||||
|
||||
|
|
@ -64,7 +69,7 @@ where
|
|||
|
||||
#[allow(clippy::while_let_loop)] // idc
|
||||
loop {
|
||||
let (tok, _) = match self.peek_t() {
|
||||
let (tok, tok_span) = match self.peek_t() {
|
||||
Ok(&tok) => tok,
|
||||
Err(_) => break,
|
||||
};
|
||||
|
|
@ -74,18 +79,48 @@ where
|
|||
break;
|
||||
}
|
||||
let (tok, _) = self.next_t()?;
|
||||
if let Tok::Punct(P::BracketOpen) = tok {
|
||||
let rhs = self.expr_bp(0)?;
|
||||
let span = expect!(self, Tok::Punct(P::BracketClose));
|
||||
let span = lhs.1.extend(span);
|
||||
lhs = (
|
||||
Expr::Binary(ExprBinary {
|
||||
lhs: Box::new(lhs),
|
||||
rhs: Box::new(rhs),
|
||||
op: BinaryOp::Index,
|
||||
}),
|
||||
span,
|
||||
);
|
||||
match tok {
|
||||
Tok::Punct(P::BracketOpen) => {
|
||||
let rhs = self.expr_bp(0)?;
|
||||
let span = expect!(self, Tok::Punct(P::BracketClose));
|
||||
let span = lhs.1.extend(span);
|
||||
lhs = (
|
||||
Expr::Binary(ExprBinary {
|
||||
lhs: Box::new(lhs),
|
||||
rhs: Box::new(rhs),
|
||||
op: BinaryOp::Index,
|
||||
}),
|
||||
span,
|
||||
);
|
||||
}
|
||||
Tok::Punct(P::ParenOpen) => {
|
||||
let mut arguments = Vec::new();
|
||||
let mut first = true;
|
||||
let last_span;
|
||||
loop {
|
||||
if let Some((_, span)) = eat!(self, Tok::Punct(P::ParenClose)) {
|
||||
last_span = span;
|
||||
break;
|
||||
}
|
||||
if !first {
|
||||
expect!(self, Tok::Punct(P::Comma));
|
||||
}
|
||||
first = false;
|
||||
|
||||
let arg = self.expr_bp(0)?;
|
||||
arguments.push(arg);
|
||||
}
|
||||
let span = tok_span.extend(last_span);
|
||||
|
||||
lhs = (
|
||||
Expr::Postfix(ExprPostfix {
|
||||
lhs: Box::new(lhs),
|
||||
op: PostfixOp::Call(arguments),
|
||||
}),
|
||||
span,
|
||||
)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -189,13 +224,13 @@ mod powers {
|
|||
pub const POSTFIX: u8 = 29;
|
||||
}
|
||||
|
||||
fn prefix_binding_power(tok: &Tok<'_>) -> u8 {
|
||||
match tok {
|
||||
fn prefix_binding_power(tok: &Tok<'_>) -> Option<u8> {
|
||||
Some(match tok {
|
||||
Tok::Punct(P::Ampersand | P::Asterisk | P::Plus | P::Minus | P::Tilde | P::Bang) => {
|
||||
powers::UNARY_OPERATOR
|
||||
}
|
||||
_ => panic!("invalid token in expression! {tok:?}"),
|
||||
}
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn infix_binding_power(tok: &Tok<'_>) -> (u8, u8) {
|
||||
|
|
@ -233,7 +268,12 @@ fn infix_binding_power(tok: &Tok<'_>) -> (u8, u8) {
|
|||
|
||||
fn postfix_binding_power(tok: &Tok<'_>) -> Option<u8> {
|
||||
match tok {
|
||||
Tok::Punct(P::BracketOpen) => Some(45),
|
||||
Tok::Punct(P::BracketOpen) => Some(powers::POSTFIX),
|
||||
Tok::Punct(P::ParenOpen) => Some(powers::POSTFIX),
|
||||
Tok::Punct(P::Dot) => Some(powers::POSTFIX),
|
||||
Tok::Punct(P::Arrow) => Some(powers::POSTFIX),
|
||||
Tok::Punct(P::PlusPlus) => Some(powers::POSTFIX),
|
||||
Tok::Punct(P::MinusMinus) => Some(powers::POSTFIX),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
source: parser/src/parser/tests.rs
|
||||
expression: "(parsed_pretty, pretty_printed_source)"
|
||||
---
|
||||
(
|
||||
Ok([
|
||||
(
|
||||
FunctionDef(FunctionDef {
|
||||
decl: Normal(NormalDecl {
|
||||
decl_spec: DeclSpec {
|
||||
ty: Integer(IntTy { sign: Signed, kind: Int }),
|
||||
attrs: "(empty)",
|
||||
},
|
||||
init_declarators: [
|
||||
(
|
||||
InitDecl {
|
||||
declarator: Declarator {
|
||||
decl: WithParams {
|
||||
ident: ("main", 5..9),
|
||||
params: [],
|
||||
},
|
||||
pointer: false,
|
||||
},
|
||||
init: None,
|
||||
},
|
||||
5..9,
|
||||
),
|
||||
],
|
||||
}),
|
||||
body: [
|
||||
(
|
||||
Expr(
|
||||
Binary(ExprBinary {
|
||||
lhs: (Atom(Int(1)), 18..19),
|
||||
rhs: (Atom(Int(1)), 22..23),
|
||||
op: Arith(Add),
|
||||
}),
|
||||
),
|
||||
18..23,
|
||||
),
|
||||
(Expr(Atom(String("hello world!"))), 29..42),
|
||||
],
|
||||
}),
|
||||
1..46,
|
||||
),
|
||||
]),
|
||||
"int main() {\n (1 + 1)\n \"hello world!\"\n}\n",
|
||||
)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
source: parser/src/parser/tests.rs
|
||||
expression: "(parsed_pretty, pretty_printed_source)"
|
||||
---
|
||||
(
|
||||
Ok([
|
||||
(
|
||||
FunctionDef(FunctionDef {
|
||||
decl: Normal(NormalDecl {
|
||||
decl_spec: DeclSpec {
|
||||
ty: Integer(IntTy { sign: Signed, kind: Int }),
|
||||
attrs: "(empty)",
|
||||
},
|
||||
init_declarators: [
|
||||
(
|
||||
InitDecl {
|
||||
declarator: Declarator {
|
||||
decl: WithParams {
|
||||
ident: ("main", 5..9),
|
||||
params: [],
|
||||
},
|
||||
pointer: false,
|
||||
},
|
||||
init: None,
|
||||
},
|
||||
5..9,
|
||||
),
|
||||
],
|
||||
}),
|
||||
body: [
|
||||
(
|
||||
Expr(
|
||||
Postfix(ExprPostfix {
|
||||
lhs: (Atom(Ident(("puts", 18..22))), 18..22),
|
||||
op: Call([(Atom(String("Hello, world!")), 23..37)]),
|
||||
}),
|
||||
),
|
||||
22..39,
|
||||
),
|
||||
],
|
||||
}),
|
||||
1..42,
|
||||
),
|
||||
]),
|
||||
"int main() {\n puts(\"Hello, world!\")\n}\n",
|
||||
)
|
||||
|
|
@ -132,4 +132,27 @@ int main() {
|
|||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expr_stmt() {
|
||||
parse_test!(
|
||||
r#"
|
||||
int main() {
|
||||
1 + 1;
|
||||
"hello world!";
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hello_world() {
|
||||
parse_test!(
|
||||
r#"
|
||||
int main() {
|
||||
puts("Hello, world!");
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ type Result = std::io::Result<()>;
|
|||
use crate::{
|
||||
ast::{
|
||||
ArithOpKind, Atom, BinaryOp, ComparisonKind, Decl, DeclAttr, DeclSpec, Declarator,
|
||||
DirectDeclarator, Expr, ExprBinary, ExprUnary, ExternalDecl, FunctionDef,
|
||||
FunctionParamDecl, InitDecl, IntTyKind, IntTySignedness, NormalDecl, Stmt, TypeSpecifier,
|
||||
UnaryOp,
|
||||
DirectDeclarator, Expr, ExprBinary, ExprPostfix, ExprUnary, ExternalDecl, FunctionDef,
|
||||
FunctionParamDecl, InitDecl, IntTyKind, IntTySignedness, NormalDecl, PostfixOp, Stmt,
|
||||
TypeSpecifier, UnaryOp,
|
||||
},
|
||||
Span, Spanned,
|
||||
};
|
||||
|
|
@ -335,6 +335,36 @@ impl<W: Write> PrettyPrinter<W> {
|
|||
Ok(())
|
||||
}
|
||||
Expr::Binary(binary) => self.binary(binary),
|
||||
Expr::Postfix(ExprPostfix { lhs, op }) => {
|
||||
self.expr(&lhs.0)?;
|
||||
match op {
|
||||
PostfixOp::Call(args) => {
|
||||
self.string("(")?;
|
||||
let mut first = true;
|
||||
for (expr, _) in args {
|
||||
if !first {
|
||||
self.string(", ")?;
|
||||
}
|
||||
first = false;
|
||||
self.expr(expr)?;
|
||||
}
|
||||
self.string(")")?;
|
||||
Ok(())
|
||||
}
|
||||
PostfixOp::Member((ident, _)) => {
|
||||
self.string(".")?;
|
||||
self.string(ident)?;
|
||||
Ok(())
|
||||
}
|
||||
PostfixOp::ArrowMember((ident, _)) => {
|
||||
self.string("->")?;
|
||||
self.string(ident)?;
|
||||
Ok(())
|
||||
}
|
||||
PostfixOp::Increment => self.string("++"),
|
||||
PostfixOp::Decrement => self.string("--"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue