vak: (Default)
[personal profile] vak
Почему бы не подурачиться 1 апреля. Думаю, парсер грамматики Си вполне сойдёт за дурацкую затею. Тем более я ж не сам напрягаться собираюсь, а ИИ подряжу. Я упоминал про ASDL, а есть ещё Ungrammar, другой способ описывать синтаксические деревья. Я попросил Грок сбацать мне грамматику языка Си. Он предложил упрощённый вариант:
// Top-level program structure
TranslationUnit = Declaration*

// Declarations
Declaration = Type Identifier ';'
| Type Identifier '(' ParameterList ')' CompoundStmt
ParameterList = (Type Identifier (',' Type Identifier)*)?

// Types
Type = 'int'
| 'float'
| 'char'
| 'void'

// Statements
Stmt = CompoundStmt
| ExprStmt
| IfStmt
| WhileStmt
| ReturnStmt

CompoundStmt = '{' Declaration* Stmt* '}'
ExprStmt = Expr ';'
IfStmt = 'if' '(' Expr ')' Stmt ('else' Stmt)?
WhileStmt = 'while' '(' Expr ')' Stmt
ReturnStmt = 'return' Expr? ';'

// Expressions
Expr = AssignmentExpr
AssignmentExpr = EqualityExpr ('=' EqualityExpr)?
EqualityExpr = RelationalExpr (('==' | '!=') RelationalExpr)?
RelationalExpr = AddExpr (('<' | '>' | '<=' | '>=') AddExpr)?
AddExpr = MultExpr (('+' | '-') MultExpr)*
MultExpr = UnaryExpr (('*' | '/') UnaryExpr)*
UnaryExpr = PrimaryExpr
| '-' UnaryExpr
| '!' UnaryExpr
PrimaryExpr = Identifier
| Number
| String
| '(' Expr ')'

// Basic tokens
Identifier = <token>
Number = <token>
String = <token>
Неплохо, вполне годится. А теперь говорю, напиши парсер этой грамматики на Rust. С третьей попытки получился работающий код: c_parser/src/main.rs. Полтыщи строк нетривиального кода одним махом побиваши.

В качестве теста обработаем Си-шную программу:
int x = 42;
int main(int argc) {
int y = 3 + 5 * 2;
if (y > x) {
return 1;
} else {
return 0;
}
}
Компилируем, запускаем:
$ cargo run
...
Running `/home/vak/c_parser/target/debug/c_parser`
TranslationUnit {
declarations: [
Variable(
Int,
"x",
Some(
Number(
42,
),
),
),
Function(
Int,
"main",
[
Parameter(
Int,
"argc",
),
],
CompoundStmt {
declarations: [
Variable(
Int,
"y",
Some(
Binary(
Number(
3,
),
Add,
Binary(
Number(
5,
),
Mul,
Number(
2,
),
),
),
),
),
],
statements: [
If(
Binary(
Identifier(
"y",
),
Greater,
Identifier(
"x",
),
),
Compound(
CompoundStmt {
declarations: [],
statements: [
Return(
Some(
Number(
1,
),
),
),
],
},
),
Some(
Compound(
CompoundStmt {
declarations: [],
statements: [
Return(
Some(
Number(
0,
),
),
),
],
},
),
),
),
],
},
),
],
}
Остаётся добавить указатели, массивы, структуры, тайпдефы и прочие фичи, и язык Си у нас в кармане. 😀
This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org