如果我们在模型文件中定义了2个简单对象,例如: -
Person
name Text
Age Int
Book
title Text
author Text
Run Code Online (Sandbox Code Playgroud)
我们可以为Book定义一个适用表格: -
addBookForm = renderDivs $ Book
<$> areq textField "title" Nothing
<*> areq textField "author" Nothing
Run Code Online (Sandbox Code Playgroud)
但是,如果我们想要将作者从一个文本字段更改为一个人的id,则:
Book
title Text
author PersonId
Run Code Online (Sandbox Code Playgroud)
然后上面的表格将无法编译,出现此错误: -
Couldn't match expected type `KeyBackend Database.Persist.GenericSql.Raw.SqlBackend Person' with actual type `Text'
Expected type: Field
sub0
master0
(KeyBackend Database.Persist.GenericSql.Raw.SqlBackend Person)
Actual type: Field sub0 master0 Text
In the first argument of `areq', namely `textField'
In the second argument of `(<*>)', namely
`areq textField "author" …Run Code Online (Sandbox Code Playgroud) 我试图看看我是否可以使用Red(或Rebol)来实现一个简单的DSL.我想将我的DSL编译为另一种语言的源代码,可能是Red或C#或两者 - 而不是直接解释和执行它.
DSL只有几个简单的语句,加上一个if/else语句.语句可以分为规则.规则将被转换为函数定义,每个语句都是目标语言中的等效语句.
Red/Rebol中的解析功能很棒,让我可以非常轻松地实现解析器 - 实际上它基本上只是语法本身的定义.
但是,我无法找到如何采取后续步骤的任何示例,特别是处理if语句并将其转换为其他源代码.翻译if语句似乎是一个很小的例子,但仍然有点棘手 - 因为在Red中有一个else意味着你需要将if改为其中一个,而不仅仅是一个额外的可选else.
传统上,在解析期间,我将构建一个抽象语法树,然后具有在AST上操作并生成新源代码的函数.我应该遵循同样的方法还是在Red中还有其他一些更惯用的方法?
我已经尝试在我的解析规则中使用collect/keep来返回嵌套块的块,这实际上形成了AST.另一种方法是将数据保存到表示不同语句等的特定对象中.
我仍然要处理收集/保留,以及何时创建新块以及将保留什么.我还想让我的解析器规则尽可能"干净",其中很少有其他代码交织在一起.所以我仍然不确定如何在解析规则的圆括号中添加红色代码.即使规则最终失败,过早添加代码也会导致Red代码被执行.添加代码太晚意味着代码可能无法按照您期望的顺序执行,尤其是在处理多级语句(如if,可能包含其他语句)时.
因此,特别是,如何将我的示例DSL转换为红色源代码的任何帮助将不胜感激.在Red或Rebol中实现这样的DSL的任何链接都会很棒!:)
这是我的解析规则: -
Red [
Purpose: example rules for parsing a simple language
]
SimpleLanguageParser: make object! [
Expr: [string! | integer! | block!]
Data: ['Person.AGE | 'Person.INCOME]
WriteMessageToLog: ['write 'message 'to 'log Expr]
SetData: ['set 'data Data '= Expr]
IfStatement: ['if Expr [any Statement] opt ['else [any Statement]] 'endif]
Statement: [WriteMessageToLog | SetData | IfStatement]
Rule: [
'rule word!
[any Statement]
'endrule
]
AnySimpLeLanguage: [Rule | …Run Code Online (Sandbox Code Playgroud)