I have been working on my own implementation of ECMAScript for quite some time. I basically did everything manually to help get a deep understanding of the process. Repeated attempts to analyze and understand this part of the grammar failed, so I worked on other parts of the project, but now I had to work on object literals at some point, so I really need to polish my parser. Can someone put this in a concept that a beginner parser could understand?
My biggest source of misunderstanding is this:
new MemberExpression arguments
This is supposed to be a member expression, but this seems to contradict the following:
NewExpression:
MemberExpression
new NewExpression
Is the new expression a member expression or an expression of the left side? Honestly, I am having problems creating the appropriate C # classes for a particular grammar.
MemberExpression:
Primaryaryionion
FunctionExpression
MemberExpression [Expression]
MemberExpression. IdentifierName
new MemberExpression Arguments
NewExpression:
MemberExpression
new NewExpression
CallExpression:
MemberExpression Arguments
CallExpression arguments
CallExpression [Expression]
CallExpression IdentifierName
LeftHandSideExpression:
NewExpression
CallExpression
This is the class I worked with, but as I continue to study the specs, my doubts just won't go away.
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)
{
}
}
Based on Andy's answer, I came up with a new design that makes sense.
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;
}
}