/// <summary> /// Consumes the stream only if the current token belongs to a command definition. /// </summary> /// <param name="styleRootNode"></param> /// <returns>true in case the current token belongs to a command definition. False if it does not.</returns> private bool TryParseCommand(StyleNodeContainer styleRootNode) { switch (tokenStream.Current.styleTokenType) { case StyleTokenType.Exit: tokenStream.Advance(); AssertTokenTypeAndAdvance(StyleTokenType.BracketClose); styleRootNode.AddChildNode(ParseRunNode(RunCommandType.Exit, ParseCommandAttribute())); return(true); case StyleTokenType.Enter: tokenStream.Advance(); AssertTokenTypeAndAdvance(StyleTokenType.BracketClose); styleRootNode.AddChildNode(ParseRunNode(RunCommandType.Enter, ParseCommandAttribute())); return(true); case StyleTokenType.EnterExit: tokenStream.Advance(); AssertTokenTypeAndAdvance(StyleTokenType.BracketClose); styleRootNode.AddChildNode(ParseRunNode(RunCommandType.EnterExit, ParseCommandAttribute())); return(true); default: return(false); } }
private void ParseStateOrAttributeGroup(StyleNodeContainer styleRootNode) { switch (tokenStream.Current.styleTokenType) { // this is the state group case StyleTokenType.Identifier: StyleStateContainer stateGroupRootNode = StyleASTNodeFactory.StateGroupRootNode(tokenStream.Current); tokenStream.Advance(); AssertTokenTypeAndAdvance(StyleTokenType.BracketClose); AssertTokenTypeAndAdvance(StyleTokenType.BracesOpen); ParseProperties(stateGroupRootNode); AssertTokenTypeAndAdvance(StyleTokenType.BracesClose); styleRootNode.AddChildNode(stateGroupRootNode); break; case StyleTokenType.AttributeSpecifier: ParseAttributeGroup(); break; default: throw new ParseException(tokenStream.Current, "Expected either a group state identifier (hover etc.)" + " or an attribute identifier (attr:...)"); } }
private void ParseProperty(StyleNodeContainer styleRootNode, bool parsingKeyframes = false) { StyleToken propertyNodeToken = tokenStream.Current; string propertyName; if (AdvanceIfTokenType(StyleTokenType.Cursor)) { propertyName = propertyNodeToken.value; } else if (AdvanceIfTokenType(StyleTokenType.Run)) { styleRootNode.AddChildNode(ParseRunNode(RunCommandType.Enter, RunAction.Run)); return; } else if (AdvanceIfTokenType(StyleTokenType.Pause)) { styleRootNode.AddChildNode(ParseRunNode(RunCommandType.Enter, RunAction.Pause)); return; } else if (AdvanceIfTokenType(StyleTokenType.Stop)) { styleRootNode.AddChildNode(ParseRunNode(RunCommandType.Enter, RunAction.Stop)); return; } else if (AdvanceIfTokenType(StyleTokenType.BracketOpen)) { if (TryParseCommand(styleRootNode)) { return; } throw new ParseException(tokenStream.Current, "Not sure what you tried here but at this point only [enter] and [exit] run animation would be legal."); } else { propertyName = AssertTokenTypeAndAdvance(StyleTokenType.Identifier); if (propertyName == "material" || propertyName == "Material") { if (tokenStream.Current == StyleTokenType.Colon) { tokenStream.Advance(); string materialName = AssertTokenTypeAndAdvance(StyleTokenType.Identifier); AssertTokenTypeAndAdvance(StyleTokenType.Dot); string materialPropertyName = AssertTokenTypeAndAdvance(StyleTokenType.Identifier); AssertTokenTypeAndAdvance(StyleTokenType.EqualSign); TextUtil.StringBuilder.Clear(); while (tokenStream.HasMoreTokens && tokenStream.Current != StyleTokenType.EndStatement) { TextUtil.StringBuilder.Append(tokenStream.Current.value); tokenStream.Advance(); } tokenStream.Advance(); MaterialPropertyNode materialPropertyNode = new MaterialPropertyNode { materialName = materialName, identifier = materialPropertyName, value = TextUtil.StringBuilder.ToString() }; TextUtil.StringBuilder.Clear(); materialPropertyNode.WithLocation(propertyNodeToken); styleRootNode.AddChildNode(materialPropertyNode); return; } } } AssertTokenTypeAndAdvance(StyleTokenType.EqualSign); PropertyNode propertyNode = StyleASTNodeFactory.PropertyNode(propertyName); propertyNode.WithLocation(propertyNodeToken); while (tokenStream.HasMoreTokens && !AdvanceIfTokenType(StyleTokenType.EndStatement)) { propertyNode.AddChildNode(ParsePropertyValue()); // we just ignore the comma for now AdvanceIfTokenType(StyleTokenType.Comma); } styleRootNode.AddChildNode(propertyNode); }
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); } } }