mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-16 17:45:11 +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,
|
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)]
|
#[derive(Debug, DebugPls)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Atom(Atom),
|
Atom(Atom),
|
||||||
Unary(ExprUnary),
|
Unary(ExprUnary),
|
||||||
Binary(ExprBinary),
|
Binary(ExprBinary),
|
||||||
|
Postfix(ExprPostfix),
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -92,7 +108,10 @@ pub enum Expr {
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls)]
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Decl(Decl),
|
Decl(Decl),
|
||||||
Labeled{label: Ident, stmt: Box<Spanned<Stmt>>},
|
Labeled {
|
||||||
|
label: Ident,
|
||||||
|
stmt: Box<Spanned<Stmt>>,
|
||||||
|
},
|
||||||
Compound(Vec<Spanned<Stmt>>),
|
Compound(Vec<Spanned<Stmt>>),
|
||||||
If {
|
If {
|
||||||
cond: Expr,
|
cond: Expr,
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ where
|
||||||
/// (6.7) declaration:
|
/// (6.7) declaration:
|
||||||
/// declaration-specifiers init-declarator-list.opt ;
|
/// declaration-specifiers init-declarator-list.opt ;
|
||||||
/// static_assert-declaration
|
/// static_assert-declaration
|
||||||
///
|
///
|
||||||
/// This does NOT eat the semicolon!
|
/// This does NOT eat the semicolon!
|
||||||
fn declaration(&mut self) -> Result<Spanned<Decl>> {
|
fn declaration(&mut self) -> Result<Spanned<Decl>> {
|
||||||
if let Some((tok, span)) = eat!(self, Tok::Kw(Kw::StaticAssert)) {
|
if let Some((tok, span)) = eat!(self, Tok::Kw(Kw::StaticAssert)) {
|
||||||
|
|
@ -201,7 +201,7 @@ where
|
||||||
/// init-declarator:
|
/// init-declarator:
|
||||||
/// declarator
|
/// declarator
|
||||||
/// declarator = initializer
|
/// declarator = initializer
|
||||||
///
|
///
|
||||||
fn init_declarator_list(&mut self) -> Result<Vec<Spanned<InitDecl>>> {
|
fn init_declarator_list(&mut self) -> Result<Vec<Spanned<InitDecl>>> {
|
||||||
let mut init_decls = Vec::new();
|
let mut init_decls = Vec::new();
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|
@ -477,7 +477,11 @@ where
|
||||||
let span2 = expect!(self, Tok::Punct(P::Semicolon));
|
let span2 = expect!(self, Tok::Punct(P::Semicolon));
|
||||||
return Ok((Stmt::Decl(decl), span.extend(span2)));
|
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:
|
/// (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
|
//! For more information, see https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{ArithOpKind, Atom, BinaryOp, ComparisonKind, Expr, ExprBinary, ExprUnary, UnaryOp},
|
ast::{
|
||||||
parser::{expect, Parser, ParserError, Result},
|
ArithOpKind, Atom, BinaryOp, ComparisonKind, Expr, ExprBinary, ExprPostfix, ExprUnary,
|
||||||
|
PostfixOp, UnaryOp,
|
||||||
|
},
|
||||||
|
parser::{expect, Parser, ParserError, Result, eat},
|
||||||
pre::Punctuator as P,
|
pre::Punctuator as P,
|
||||||
token::{Constant, Token as Tok},
|
token::{Constant, Token as Tok},
|
||||||
Span, Spanned,
|
Span, Spanned,
|
||||||
|
|
@ -33,7 +36,9 @@ where
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
&(Tok::Punct(punct), span) => {
|
&(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 Some(op) = unary_op_from_token(&Tok::Punct(punct)) else { panic!() };
|
||||||
let rhs = self.expr_bp(r_bp)?;
|
let rhs = self.expr_bp(r_bp)?;
|
||||||
|
|
||||||
|
|
@ -64,7 +69,7 @@ where
|
||||||
|
|
||||||
#[allow(clippy::while_let_loop)] // idc
|
#[allow(clippy::while_let_loop)] // idc
|
||||||
loop {
|
loop {
|
||||||
let (tok, _) = match self.peek_t() {
|
let (tok, tok_span) = match self.peek_t() {
|
||||||
Ok(&tok) => tok,
|
Ok(&tok) => tok,
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
};
|
};
|
||||||
|
|
@ -74,18 +79,48 @@ where
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let (tok, _) = self.next_t()?;
|
let (tok, _) = self.next_t()?;
|
||||||
if let Tok::Punct(P::BracketOpen) = tok {
|
match tok {
|
||||||
let rhs = self.expr_bp(0)?;
|
Tok::Punct(P::BracketOpen) => {
|
||||||
let span = expect!(self, Tok::Punct(P::BracketClose));
|
let rhs = self.expr_bp(0)?;
|
||||||
let span = lhs.1.extend(span);
|
let span = expect!(self, Tok::Punct(P::BracketClose));
|
||||||
lhs = (
|
let span = lhs.1.extend(span);
|
||||||
Expr::Binary(ExprBinary {
|
lhs = (
|
||||||
lhs: Box::new(lhs),
|
Expr::Binary(ExprBinary {
|
||||||
rhs: Box::new(rhs),
|
lhs: Box::new(lhs),
|
||||||
op: BinaryOp::Index,
|
rhs: Box::new(rhs),
|
||||||
}),
|
op: BinaryOp::Index,
|
||||||
span,
|
}),
|
||||||
);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -189,13 +224,13 @@ mod powers {
|
||||||
pub const POSTFIX: u8 = 29;
|
pub const POSTFIX: u8 = 29;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prefix_binding_power(tok: &Tok<'_>) -> u8 {
|
fn prefix_binding_power(tok: &Tok<'_>) -> Option<u8> {
|
||||||
match tok {
|
Some(match tok {
|
||||||
Tok::Punct(P::Ampersand | P::Asterisk | P::Plus | P::Minus | P::Tilde | P::Bang) => {
|
Tok::Punct(P::Ampersand | P::Asterisk | P::Plus | P::Minus | P::Tilde | P::Bang) => {
|
||||||
powers::UNARY_OPERATOR
|
powers::UNARY_OPERATOR
|
||||||
}
|
}
|
||||||
_ => panic!("invalid token in expression! {tok:?}"),
|
_ => return None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infix_binding_power(tok: &Tok<'_>) -> (u8, u8) {
|
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> {
|
fn postfix_binding_power(tok: &Tok<'_>) -> Option<u8> {
|
||||||
match tok {
|
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,
|
_ => 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::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
ArithOpKind, Atom, BinaryOp, ComparisonKind, Decl, DeclAttr, DeclSpec, Declarator,
|
ArithOpKind, Atom, BinaryOp, ComparisonKind, Decl, DeclAttr, DeclSpec, Declarator,
|
||||||
DirectDeclarator, Expr, ExprBinary, ExprUnary, ExternalDecl, FunctionDef,
|
DirectDeclarator, Expr, ExprBinary, ExprPostfix, ExprUnary, ExternalDecl, FunctionDef,
|
||||||
FunctionParamDecl, InitDecl, IntTyKind, IntTySignedness, NormalDecl, Stmt, TypeSpecifier,
|
FunctionParamDecl, InitDecl, IntTyKind, IntTySignedness, NormalDecl, PostfixOp, Stmt,
|
||||||
UnaryOp,
|
TypeSpecifier, UnaryOp,
|
||||||
},
|
},
|
||||||
Span, Spanned,
|
Span, Spanned,
|
||||||
};
|
};
|
||||||
|
|
@ -335,6 +335,36 @@ impl<W: Write> PrettyPrinter<W> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Expr::Binary(binary) => self.binary(binary),
|
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