Я работаю над собственной реализацией ECMAScript уже довольно давно. Я в основном сделал все вручную, чтобы помочь глубже понять процесс. Повторные попытки проанализировать и понять эту часть грамматики не увенчались успехом, поэтому я работал над другими частями проекта, но сейчас я нахожусь в какой-то момент, когда буду работать над объектными литералами, поэтому мне действительно нужно отполировать мой синтаксический анализатор. Кто-нибудь может выразить это словами, которые может понять новичок в синтаксическом анализаторе языка?
Мой самый большой источник путаницы заключается в следующем:
Аргументы новых выражений членов
Предполагается, что это выражение члена, но, похоже, это противоречит следующему:
NewExpression :
MemberExpression
new NewExpression
Является ли новое выражение выражением-членом или левосторонним выражением? Честно говоря, у меня проблемы с выкладыванием надлежащих классов C # для конкретной грамматики.
MemberExpression :
PrimaryExpression
FunctionExpression
MemberExpression [ Expression ]
MemberExpression . IdentifierName
new MemberExpression Arguments
NewExpression :
MemberExpression
new NewExpression
CallExpression :
MemberExpression Arguments
CallExpression Arguments
CallExpression [ Expression ]
CallExpression . IdentifierName
LeftHandSideExpression :
NewExpression
CallExpression
Это дизайн класса, с которым я работал, но когда я продолжаю изучать спецификацию, мои сомнения просто не исчезнут.
public abstract class LeftHandSideExpression : ConcreteExpression
{
}
public sealed class NewExpression : LeftHandSideExpression
{
public NewExpression(MemberExpression memberExpression, Arguments arguments)
{
}
public NewExpression(NewExpression newExpression, Arguments arguments)
{
}
}
public sealed class CallExpression : LeftHandSideExpression
{
public CallExpression(MemberExpression memberExpression, Arguments arguments)
{
}
public CallExpression(CallExpression callExpression, Arguments arguments)
{
}
}
public sealed class MemberExpression : ConcreteExpression
{
public MemberExpression(PrimaryExpression primaryExpression)
{
}
public MemberExpression(PrimaryExpression primaryExpression, string identifierName)
{
}
public MemberExpression(PrimaryExpression primaryExpression, ConcreteExpression indexerExpression)
{
}
public MemberExpression(FunctionExpression functionExpression)
{
}
public MemberExpression(FunctionExpression functionExpression, string identifierName)
{
}
public MemberExpression(FunctionExpression functionExpression, ConcreteExpression indexerExpression)
{
}
}
Основываясь на ответе Энди, я придумал новый дизайн, который имеет смысл.
public abstract class LeftHandSideExpression : ConcreteExpression
{
public ConcreteExpression Expression { get; private set; }
protected LeftHandSideExpression(ConcreteExpression expression)
{
Expression = expression;
}
}
public class NewExpression : LeftHandSideExpression
{
public Arguments Arguments { get; private set; }
protected NewExpression(PrimaryExpression primaryExpression)
: base(primaryExpression)
{
}
protected NewExpression(FunctionExpression functionExpression)
: base(functionExpression)
{
}
protected NewExpression(MemberExpression memberExpression)
: base(memberExpression)
{
}
protected NewExpression(CallExpression callExpression)
: base(callExpression)
{
}
public NewExpression(MemberExpression memberExpression, Arguments arguments)
: base(memberExpression)
{
Arguments = arguments;
}
public NewExpression(NewExpression newExpression, Arguments arguments)
: base(newExpression)
{
Arguments = arguments;
}
}
public sealed class CallExpression : LeftHandSideExpression
{
public Arguments Arguments { get; private set; }
public CallExpression(MemberExpression memberExpression, Arguments arguments)
: base(memberExpression)
{
Arguments = arguments;
}
public CallExpression(CallExpression callExpression, Arguments arguments)
: base(callExpression)
{
Arguments = arguments;
}
}
public class MemberExpression : NewExpression
{
public MemberExpression(PrimaryExpression primaryExpression)
: base(primaryExpression)
{
}
public MemberExpression(FunctionExpression functionExpression)
: base(functionExpression)
{
}
public MemberExpression(MemberExpression memberExpression)
: base(memberExpression)
{
}
protected MemberExpression(CallExpression callExpression)
: base(callExpression)
{
}
}
public sealed class DotPropertyAccessExpression : MemberExpression
{
public string IdentifierName { get; private set; }
public DotPropertyAccessExpression(PrimaryExpression primaryExpression, string identifierName)
: base(primaryExpression)
{
IdentifierName = identifierName;
}
public DotPropertyAccessExpression(FunctionExpression functionExpression, string identifierName)
: base(functionExpression)
{
IdentifierName = identifierName;
}
public DotPropertyAccessExpression(MemberExpression memberExpression, string identifierName)
: base(memberExpression)
{
IdentifierName = identifierName;
}
public DotPropertyAccessExpression(CallExpression callExpression, string identifierName)
: base(callExpression)
{
IdentifierName = identifierName;
}
}
public sealed class BracketPropertyAccessExpression : MemberExpression
{
public ConcreteExpression IndexerExpression { get; private set; }
public BracketPropertyAccessExpression(PrimaryExpression primaryExpression, ConcreteExpression indexerExpression)
: base(primaryExpression)
{
IndexerExpression = indexerExpression;
}
public BracketPropertyAccessExpression(FunctionExpression functionExpression, ConcreteExpression indexerExpression)
: base(functionExpression)
{
IndexerExpression = indexerExpression;
}
public BracketPropertyAccessExpression(MemberExpression memberExpression, ConcreteExpression indexerExpression)
: base(memberExpression)
{
IndexerExpression = indexerExpression;
}
public BracketPropertyAccessExpression(CallExpression callExpression, ConcreteExpression indexerExpression)
: base(callExpression)
{
IndexerExpression = indexerExpression;
}
}