tokenlist_stmt new_lst |> parseStmtList
Здесь вы применяете tokenlist_stmt
к аргументу new_lst
, а затем применяете parseStmtList
к результату.Но tokenlist_stmt
на самом деле не функция, так что это ошибка типа.
Предположительно, вы намеревались вызвать parseStmtList
с tokenlist_stmt
и new_lst
в качестве двух аргументов.Синтаксис для этого просто:
parseStmtList tokenlist_stmt new_lst
Далее lst::stmt
также является ошибкой типа по двум причинам:
::
принимает список в качестве правого операнда, а неслева, так что это должно быть stmt::lst
lst
на самом деле не список, это Ast.Block
, потому что это то, что parseStmtList
возвращает.
Как только выисправив все это, вы заметите, что список будет неправильным (вероятно, именно поэтому вы сначала попытались lst::stmt
, но вы не можете добавить в конец такого списка).Это общая проблема при создании списка с помощью аккумулятора.Решение состоит в том, чтобы либо перевернуть список, как только вы закончили его построение, либо вообще не использовать аккумулятор.
Важно отметить, что все эти проблемы будут иметьприменяется также при использовании Ast.stmtlist
.То есть, если бы ваш код выглядел так:
let new_lst = Ast.StmtList(lst, stmt) in
let (tokenlist_stmt_list, stmt_list) = tokenlist_stmt new_lst |> parseStmtList in
(tokenlist_stmt_list, Ast.Block(stmt_lst))
Тогда вы получите точно такие же ошибки.Это заставляет меня думать, что вы изменили намного больше кода, чем нужно.Поскольку ваш старый код предположительно работал, я предполагаю, что он выглядел примерно так:
let rec parseStmtList tokenlist =
match tokenlist.head with
| Lexer.RightBrace -> (tokenlist, Ast.StmtlistNil )
| _ -> let (tokenlist_stmt, stmt) = parseStmt tokenlist in
let (tokenlist_stmt_list, stmt_list) = parseStmtList tokenlist_stmt in
(tokenlist_stmt_list, Ast.StmtList (stmt, stmt_lst))
, а затем в parseStmt
у вас было:
let (tokenlist_stmtlist, stmtlist) = parseStmtList tokenlist_leftbrace in
begin
match tokenlist_expr.head with
| Lexer.RightBrace -> (next tokenlist_stmtlist, Ast.Block(stmtlist))
Теперь после удаления Ast.stmtlist
все, что вам нужно изменить, это части, где вы фактически использовали его конструкторы, и замените эти части конструкторами списков (::
и []
).Таким образом, код в parseStmt
остался бы полностью неизменным, и единственные изменения в parseStmtList
должны состоять в том, чтобы заменить строку
| Lexer.RightBrace -> (tokenlist, Ast.StmtlistNil )
на
| Lexer.RightBrace -> (tokenlist, [] )
и строку
(tokenlist_stmt_list, Ast.StmtList (stmt, stmt_lst))
с
(tokenlist_stmt_list, stmt :: stmt_lst)
Если ваш старый код выглядел иначе, чем я придумал выше, вам, возможно, придется изменить другие строки, но идея остается прежней: замените Ast.StmtList
на::
и Ast.StmtListNil
с []
.
И все.Это все изменения, которые необходимы.Вы были слишком сложны.