vak: (Default)
Serge Vakulenko ([personal profile] vak) wrote2025-04-01 02:52 pm

Ungrammar

Почему бы не подурачиться 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,
),
),
),
],
},
),
),
),
],
},
),
],
}
Остаётся добавить указатели, массивы, структуры, тайпдефы и прочие фичи, и язык Си у нас в кармане. 😀
spamsink: (Default)

[personal profile] spamsink 2025-04-02 01:47 am (UTC)(link)
Ну Семён Семёныч! Надо-то было "напиши парсер этой грамматики на Pascal"!

spamsink: (Default)

[personal profile] spamsink 2025-04-02 08:40 am (UTC)(link)
Смотри-ка, умеет, когда хочет. Надо будет воспользоваться со временем, для переписывания парсера.
juan_gandhi: (Default)

[personal profile] juan_gandhi 2025-04-02 05:42 am (UTC)(link)
Ха, красивое!
juan_gandhi: (Default)

[personal profile] juan_gandhi 2025-04-02 05:43 am (UTC)(link)
Остаётся вот это ещё добавить: https://habr.com/en/articles/895882/
juan_gandhi: (Default)

[personal profile] juan_gandhi 2025-04-02 08:01 am (UTC)(link)
Ого! Пол тряпкой!
chaource: (Default)

[personal profile] chaource 2025-04-02 07:15 pm (UTC)(link)
Я такъ и не понялъ пока что смыслъ этого "Ungrammar". По-моему, это никакъ не отличается отъ обычныхъ декларативныхъ грамматикъ, которыя обычно пишутся на языкахъ программированiя.