private void ParseAttributeGroup() { AssertTokenTypeAndAdvance(StyleTokenType.AttributeSpecifier); AssertTokenTypeAndAdvance(StyleTokenType.Colon); StyleToken attributeToken = tokenStream.Current; string attributeIdentifier = AssertTokenTypeAndAdvance(StyleTokenType.Identifier); string attributeValue = null; if (AdvanceIfTokenType(StyleTokenType.EqualSign)) { attributeValue = tokenStream.Current.value; tokenStream.Advance(); } bool invert = groupOperatorStack.Count > 0 && groupOperatorStack.Pop() == StyleOperatorType.Not; AttributeNodeContainer andAttribute = groupExpressionStack.Count > 0 ? groupExpressionStack.Pop() : null; AttributeNodeContainer attributeNodeContainer = StyleASTNodeFactory.AttributeGroupRootNode(attributeIdentifier, attributeValue, invert, andAttribute); attributeNodeContainer.WithLocation(attributeToken); groupExpressionStack.Push(attributeNodeContainer); AssertTokenTypeAndAdvance(StyleTokenType.BracketClose); }
private void ParseStyleGroupBody(StyleNodeContainer styleRootNode) { AssertTokenTypeAndAdvance(StyleTokenType.BracesOpen); while (tokenStream.HasMoreTokens && !AdvanceIfTokenType(StyleTokenType.BracesClose)) { switch (tokenStream.Current.styleTokenType) { case StyleTokenType.Not: { groupOperatorStack.Push(StyleOperatorType.Not); tokenStream.Advance(); ParseAttributeOrExpressionGroup(); break; } case StyleTokenType.And: tokenStream.Advance(); if (AdvanceIfTokenType(StyleTokenType.Not)) { groupOperatorStack.Push(StyleOperatorType.Not); } ParseAttributeOrExpressionGroup(); break; case StyleTokenType.BracketOpen: tokenStream.Advance(); if (!TryParseCommand(styleRootNode)) { ParseStateOrAttributeGroup(styleRootNode); } break; case StyleTokenType.Cursor: // special case here: we are out of words and need to use the // cursor token for the property AND the top level definition ¯\_(ツ)_/¯ ParseProperty(styleRootNode); break; case StyleTokenType.Identifier: ParseProperty(styleRootNode); break; case StyleTokenType.Run: tokenStream.Advance(); styleRootNode.AddChildNode(ParseRunNode(RunCommandType.Enter, RunAction.Run)); break; case StyleTokenType.Stop: tokenStream.Advance(); styleRootNode.AddChildNode(ParseRunNode(RunCommandType.Enter, RunAction.Stop)); break; case StyleTokenType.Pause: tokenStream.Advance(); styleRootNode.AddChildNode(ParseRunNode(RunCommandType.Enter, RunAction.Pause)); break; case StyleTokenType.BracesOpen: { // At this point only unconsumed attribute/expression group bodies are allowed if (groupExpressionStack.Count > 1) { throw new ParseException(tokenStream.Current, "There was a problem, I somehow made an error parsing a combined style group..."); } if (groupExpressionStack.Count == 1) { AttributeNodeContainer attributeNodeContainer = groupExpressionStack.Pop(); ParseStyleGroupBody(attributeNodeContainer); styleRootNode.AddChildNode(attributeNodeContainer); } else { throw new ParseException(tokenStream.Current, "Expected an attribute style group body. Braces are in a weird position!"); } break; } default: throw new ParseException(tokenStream.Current, "Expected either a boolean group operator (not / and), the start" + " of a group (an open bracket) or a regular property identifier but found " + tokenStream.Current.styleTokenType + " with value " + tokenStream.Current.value); } } }