あなたは正しく、内部について多くのことを知らなくても、ペグの生成されたパーサーを即座に変更することはできません。しかし、標準的なLALRからあなたが失うものは、パーサーのルール全体を通してJavaScriptコードを散らばっています。
あなたの目標を達成するには、次のように、(文脈で)新しいタイプを認識し、後で使用するためにそれらを維持する必要があります:
{
// predefined types
const types = {'int':true, 'float':true, 'string':true}
// variable storage
const vars = {}
}
start = statement statement* {
console.log(JSON.stringify({types:types,vars:vars}, null, 2))
}
statement
= WS* typedef EOL
/WS* vardef EOL
typedef "new type definition" // eg. 'define myNewType'
= 'define' SP+ type:symbol {
if(types[type]) {
throw `attempted redefinition of: "${type}"`
}
types[type]=true
}
// And then, when you need to recognize a type, something like:
vardef "variable declaration" // eg: 'let foo:myNewType=10'
= 'let' SP+ name:symbol COLON type:symbol SP* value:decl_assign? {
if(!types[type]) {
throw `unknown type encountered: ${type}`
}
vars[name] = { name: name, type:type, value: value }
}
decl_assign "variable declaration assignment"
= '=' SP* value:number {
return value
}
symbol = $([a-zA-Z][a-zA-Z0-9]*)
number = $(('+'/'-')? [1-9][0-9]* ('.' [0-9]+)?)
COLON = ':'
SP = [ \t]
WS = [ \t\n]
EOL = '\n'
れ、解析するように求められたとき:
define fooType
let bar:fooType = 1
が印刷されます:私はあなたが、あなたは基本的に型を作り、同じことを識別子、およびCONTに依存している何を言っているか理解していれば
{
"types": {
"int": true,
"float": true,
"string": true,
"fooType": true
},
"vars": {
"bar": {
"name": "bar",
"type": "fooType",
"value": "1"
}
}
}
あなたが探しているものを決定するために内線? – Michael
はい。彼らが定義の文脈の中に現れたら、それらをインターンします。そして、それが他の文脈で起こったときは、黙った定義を参照してください。 –
幸運にも私がパーサーを書く言語は、このように動作しますが、運が悪い言語はないと思います – Michael