如何解析在解析期间定义的类型名称
How to parse type names defined during parse
我正在使用 pegjs 来定义允许定义新类型的语法。那么我如何在定义之后识别这些类型?我有一个定义内置类型的产品,例如
BuiltInType
= "int"
/ "float"
/ "string"
/ TYPE_NAME
但是最后一个我该怎么办?在源代码中定义之前,我不知道哪些字符串可能是类型名称。
在既有词法分析器又有解析器的传统解析方式中,解析器会将类型名称添加到 table 中,词法分析器会使用此 table 来确定是否return TYPE_NAME 或特定令牌的 IDENTIFIER。但是pegjs没有这个分离。
你是对的,如果不了解 pegjs 的内部结构,就不能(轻松地)即时修改 pegjs 生成的解析器。但是你从标准 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
将打印:
{
"types": {
"int": true,
"float": true,
"string": true,
"fooType": true
},
"vars": {
"bar": {
"name": "bar",
"type": "fooType",
"value": "1"
}
}
}
我正在使用 pegjs 来定义允许定义新类型的语法。那么我如何在定义之后识别这些类型?我有一个定义内置类型的产品,例如
BuiltInType
= "int"
/ "float"
/ "string"
/ TYPE_NAME
但是最后一个我该怎么办?在源代码中定义之前,我不知道哪些字符串可能是类型名称。
在既有词法分析器又有解析器的传统解析方式中,解析器会将类型名称添加到 table 中,词法分析器会使用此 table 来确定是否return TYPE_NAME 或特定令牌的 IDENTIFIER。但是pegjs没有这个分离。
你是对的,如果不了解 pegjs 的内部结构,就不能(轻松地)即时修改 pegjs 生成的解析器。但是你从标准 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
将打印:
{
"types": {
"int": true,
"float": true,
"string": true,
"fooType": true
},
"vars": {
"bar": {
"name": "bar",
"type": "fooType",
"value": "1"
}
}
}