system/src/sc/parser/NestedParselet.java
public boolean semanticPropertyChanged(Object parentParseNode, Object semanticValue, Object selector, Object value) {
      int slotIx = getSlotIndex(selector);

      // Not our immediate property - we propagate it down
      if (slotIx == -1) {
         int chainIx;
         if (parameterType == ParameterType.PROPAGATE && propagatedValueIndex != -1) {
            ParentParseNode ppnode = (ParentParseNode) parentParseNode;

            // Already invalidated
            if (ppnode.children == null)
               return true;

            /*
             * In some cases, the type might either be propagated or inherited.  In these cases, we cannot regen
             * incrementally.
             */
            if (ppnode.children.size() <= propagatedValueIndex)
               return regenerateIfTracking(ppnode, false);
            Parselet childParselet = parselets.get(propagatedValueIndex);
            if (childParselet instanceof NestedParselet) {
               Object childParseNode = ppnode.children.get(propagatedValueIndex);
               // At least one case where this happens is for IdentifierExpression(identifiers,.) when we
               // add "arguments" to the expression. 
               if (childParseNode == null)
                  return regenerateIfTracking(ppnode, false);

               // Some parselets do not generate a parse node - rather they just propagate up the nested parselets
               // value.  We'll skip passed these parselets during the generation.
               if (childParseNode instanceof IParseNode) {
                  childParselet = ((IParseNode) childParseNode).getParselet();
               }
               // This parsenode was optimized into a String so we can't do any incremental updates
               else if (childParseNode instanceof String)
                  return regenerateIfTracking(ppnode, false);
               return ((NestedParselet) childParselet).semanticPropertyChanged(childParseNode, semanticValue, selector, value);
            }
            else
               throw new IllegalArgumentException("Unable to update semantic property value");
         }
         // If we have an "*" operators, see if we can propagate the change to a child.
         else if (inheritSlots != null) {
            ParentParseNode ppnode = (ParentParseNode) parentParseNode;
            for (int i = 0; i < inheritSlots.size(); i++) {
               int slot = inheritSlots.get(i);
               NestedParselet child = (NestedParselet) parselets.get(slot);
               // This checks the "*"'s recursively down the tree to see which parselet produces this property
               if (child.handlesProperty(selector)) {
                  Object childParseNode = ppnode.children == null || slot > ppnode.children.size() ? null : ppnode.children.get(slot);
                  if (childParseNode == null)
                     return regenerateIfTracking(ppnode, false);
                  return child.semanticPropertyChanged(childParseNode, semanticValue, selector, value);
               }
            }
            return false;
         }
         else if ((chainIx = getChainedPropertyIndex(selector)) != -1) {
            ParentParseNode ppnode = (ParentParseNode) parentParseNode;
            if (chainIx == 0) {
               ISemanticNode isn = (ISemanticNode) semanticValue;
               ISemanticNode parent = isn.getParentNode();
               ParentParseNode parentParentParseNode = (ParentParseNode) parent.getParseNode();
               return parentParentParseNode.parselet.regenerateIfTracking(parentParentParseNode, false);
            }
            else
               return regenerateIfTracking(ppnode, false);
         }
         else // We are given a property change for a node we don't know about - return an error so we try the next choice
            return false;
      }
      else {
         Object newChildParseNode;
         Parselet childParselet = parselets.get(slotIx);

         /*
         Object oldValue = TypeUtil.getPropertyValue(this, selector);
         if (oldValue == value || (oldValue != null && oldValue.equals(value)))
            return;

         if (oldValue instanceof ISemanticNode)
         {
            ISemanticNode oldSemanticNode = (ISemanticNode) oldValue;
            oldChildParseNode = oldSemanticNode.getParseNode();
         }
         else
            oldChildParseNode = oldValue;
         */

         if (value instanceof ISemanticNode) {
            if (language.trackChanges || !(parentParseNode instanceof ParentParseNode)) {
               Object obj = childParselet.generate(getLanguage().newGenerateContext(this, value), value);
               if (obj instanceof IParseNode)
                  newChildParseNode = (IParseNode) obj;
               else // GenerateError...
                  return false;
            }
            else {
               ParentParseNode ppnode = (ParentParseNode) parentParseNode;
               // If the parent node has already been invalidated, we should not need to create the children just to maintain
               // a ref point, since the parent will get entirely regenerated anyway.
               if (ppnode.children == null) {
                  return true;
               }
               invalidateChildParseNode(ppnode, childParselet, value, slotIx, slotIx <= ppnode.children.size() ? ChangeType.REPLACE : ChangeType.ADD);
               return true;
            }
         }
         else {
            // Used to just use "value" here for the child parse node but that omits spacing
            newChildParseNode = value == null ? null : childParselet.generate(getLanguage().newGenerateContext(this, value), value);
            if (newChildParseNode instanceof GenerateError) {
               System.err.println("*** value could not generate");
               return false;
            }
         }

         ParentParseNode ppnode = (ParentParseNode) parentParseNode;

         // Right now, we are just replacing the value.  We could potentially try to merge the values to
         // preserve comments in the whitespace or something like that.  Possibly this should be a hook
         // on the parent or child parselet so it gets to merge updated parse nodes together?
         if (ppnode.children == null || slotIx >= ppnode.children.size())
            ppnode.addGeneratedNode(newChildParseNode, childParselet);
         else
            ppnode.children.set(slotIx, newChildParseNode);
         //parentParseNode.replace(oldChildParseNode, newChildParseNode, childParselet, slotIx);

         return true;
      }
   }
/**
    * For a given parse node which we generated (or null).  Returns false if the parselet is unable to handle
    * the change.  For a choice, this might be a signal to try another alternative.
    */
For a given parse node which we generated (or null).  Returns false if the parselet is unable to handle
the change.  For a choice, this might be a signal to try another alternative.
For a given parse node which we generated ( or null ) . Returns false if the parselet is unable to handle the change . For a choice this might be a signal to try another alternative .
public boolean semanticPropertyChanged(Object parentParseNode, Object semanticValue, Object selector, Object value) {
      int slotIx = getSlotIndex(selector);
      if (slotIx == -1) {
         int chainIx;
         if (parameterType == ParameterType.PROPAGATE && propagatedValueIndex != -1) {
            ParentParseNode ppnode = (ParentParseNode) parentParseNode;
            if (ppnode.children == null)
               return true;
            /*
             * In some cases, the type might either be propagated or inherited.  In these cases, we cannot regen
             * incrementally.
             */
            if (ppnode.children.size() <= propagatedValueIndex)
               return regenerateIfTracking(ppnode, false);
            Parselet childParselet = parselets.get(propagatedValueIndex);
            if (childParselet instanceof NestedParselet) {
               Object childParseNode = ppnode.children.get(propagatedValueIndex);
               if (childParseNode == null)
                  return regenerateIfTracking(ppnode, false);
               if (childParseNode instanceof IParseNode) {
                  childParselet = ((IParseNode) childParseNode).getParselet();
               }
               else if (childParseNode instanceof String)
                  return regenerateIfTracking(ppnode, false);
               return ((NestedParselet) childParselet).semanticPropertyChanged(childParseNode, semanticValue, selector, value);
            }
            else
               throw new IllegalArgumentException("Unable to update semantic property value");
         }
         else if (inheritSlots != null) {
            ParentParseNode ppnode = (ParentParseNode) parentParseNode;
            for (int i = 0; i < inheritSlots.size(); i++) {
               int slot = inheritSlots.get(i);
               NestedParselet child = (NestedParselet) parselets.get(slot);
               if (child.handlesProperty(selector)) {
                  Object childParseNode = ppnode.children == null || slot > ppnode.children.size() ? null : ppnode.children.get(slot);
                  if (childParseNode == null)
                     return regenerateIfTracking(ppnode, false);
                  return child.semanticPropertyChanged(childParseNode, semanticValue, selector, value);
               }
            }
            return false;
         }
         else if ((chainIx = getChainedPropertyIndex(selector)) != -1) {
            ParentParseNode ppnode = (ParentParseNode) parentParseNode;
            if (chainIx == 0) {
               ISemanticNode isn = (ISemanticNode) semanticValue;
               ISemanticNode parent = isn.getParentNode();
               ParentParseNode parentParentParseNode = (ParentParseNode) parent.getParseNode();
               return parentParentParseNode.parselet.regenerateIfTracking(parentParentParseNode, false);
            }
            else
               return regenerateIfTracking(ppnode, false);
         }
         else 
            return false;
      }
      else {
         Object newChildParseNode;
         Parselet childParselet = parselets.get(slotIx);
         /*
         Object oldValue = TypeUtil.getPropertyValue(this, selector);
         if (oldValue == value || (oldValue != null && oldValue.equals(value)))
            return;
         if (oldValue instanceof ISemanticNode)
         {
            ISemanticNode oldSemanticNode = (ISemanticNode) oldValue;
            oldChildParseNode = oldSemanticNode.getParseNode();
         }
         else
            oldChildParseNode = oldValue;
         */
         if (value instanceof ISemanticNode) {
            if (language.trackChanges || !(parentParseNode instanceof ParentParseNode)) {
               Object obj = childParselet.generate(getLanguage().newGenerateContext(this, value), value);
               if (obj instanceof IParseNode)
                  newChildParseNode = (IParseNode) obj;
               else 
                  return false;
            }
            else {
               ParentParseNode ppnode = (ParentParseNode) parentParseNode;
               if (ppnode.children == null) {
                  return true;
               }
               invalidateChildParseNode(ppnode, childParselet, value, slotIx, slotIx <= ppnode.children.size() ? ChangeType.REPLACE : ChangeType.ADD);
               return true;
            }
         }
         else {
            newChildParseNode = value == null ? null : childParselet.generate(getLanguage().newGenerateContext(this, value), value);
            if (newChildParseNode instanceof GenerateError) {
               System.err.println("*** value could not generate");
               return false;
            }
         }
         ParentParseNode ppnode = (ParentParseNode) parentParseNode;
         if (ppnode.children == null || slotIx >= ppnode.children.size())
            ppnode.addGeneratedNode(newChildParseNode, childParselet);
         else
            ppnode.children.set(slotIx, newChildParseNode);
         return true;
      }
   }
public boolean semanticPropertyChanged ( Object parentParseNode , Object semanticValue , Object selector , Object value ) { int slotIx = getSlotIndex ( selector ) ; if ( slotIx == - 1 ) { int chainIx ; if ( parameterType == ParameterType . PROPAGATE && propagatedValueIndex != - 1 ) { ParentParseNode ppnode = ( ParentParseNode ) parentParseNode ; if ( ppnode . children == null ) return true ; /*
             * In some cases, the type might either be propagated or inherited.  In these cases, we cannot regen
             * incrementally.
             */ if ( ppnode . children . size ( ) <= propagatedValueIndex ) return regenerateIfTracking ( ppnode , false ) ; Parselet childParselet = parselets . get ( propagatedValueIndex ) ; if ( childParselet instanceof NestedParselet ) { Object childParseNode = ppnode . children . get ( propagatedValueIndex ) ; if ( childParseNode == null ) return regenerateIfTracking ( ppnode , false ) ; if ( childParseNode instanceof IParseNode ) { childParselet = ( ( IParseNode ) childParseNode ) . getParselet ( ) ; } else if ( childParseNode instanceof String ) return regenerateIfTracking ( ppnode , false ) ; return ( ( NestedParselet ) childParselet ) . semanticPropertyChanged ( childParseNode , semanticValue , selector , value ) ; } else throw new IllegalArgumentException ( "Unable to update semantic property value" ) ; } else if ( inheritSlots != null ) { ParentParseNode ppnode = ( ParentParseNode ) parentParseNode ; for ( int i = 0 ; i < inheritSlots . size ( ) ; i ++ ) { int slot = inheritSlots . get ( i ) ; NestedParselet child = ( NestedParselet ) parselets . get ( slot ) ; if ( child . handlesProperty ( selector ) ) { Object childParseNode = ppnode . children == null || slot > ppnode . children . size ( ) ? null : ppnode . children . get ( slot ) ; if ( childParseNode == null ) return regenerateIfTracking ( ppnode , false ) ; return child . semanticPropertyChanged ( childParseNode , semanticValue , selector , value ) ; } } return false ; } else if ( ( chainIx = getChainedPropertyIndex ( selector ) ) != - 1 ) { ParentParseNode ppnode = ( ParentParseNode ) parentParseNode ; if ( chainIx == 0 ) { ISemanticNode isn = ( ISemanticNode ) semanticValue ; ISemanticNode parent = isn . getParentNode ( ) ; ParentParseNode parentParentParseNode = ( ParentParseNode ) parent . getParseNode ( ) ; return parentParentParseNode . parselet . regenerateIfTracking ( parentParentParseNode , false ) ; } else return regenerateIfTracking ( ppnode , false ) ; } else return false ; } else { Object newChildParseNode ; Parselet childParselet = parselets . get ( slotIx ) ; /*
         Object oldValue = TypeUtil.getPropertyValue(this, selector);
         if (oldValue == value || (oldValue != null && oldValue.equals(value)))
            return;

         if (oldValue instanceof ISemanticNode)
         {
            ISemanticNode oldSemanticNode = (ISemanticNode) oldValue;
            oldChildParseNode = oldSemanticNode.getParseNode();
         }
         else
            oldChildParseNode = oldValue;
         */ if ( value instanceof ISemanticNode ) { if ( language . trackChanges || ! ( parentParseNode instanceof ParentParseNode ) ) { Object obj = childParselet . generate ( getLanguage ( ) . newGenerateContext ( this , value ) , value ) ; if ( obj instanceof IParseNode ) newChildParseNode = ( IParseNode ) obj ; else return false ; } else { ParentParseNode ppnode = ( ParentParseNode ) parentParseNode ; if ( ppnode . children == null ) { return true ; } invalidateChildParseNode ( ppnode , childParselet , value , slotIx , slotIx <= ppnode . children . size ( ) ? ChangeType . REPLACE : ChangeType . ADD ) ; return true ; } } else { newChildParseNode = value == null ? null : childParselet . generate ( getLanguage ( ) . newGenerateContext ( this , value ) , value ) ; if ( newChildParseNode instanceof GenerateError ) { System . err . println ( "*** value could not generate" ) ; return false ; } } ParentParseNode ppnode = ( ParentParseNode ) parentParseNode ; if ( ppnode . children == null || slotIx >= ppnode . children . size ( ) ) ppnode . addGeneratedNode ( newChildParseNode , childParselet ) ; else ppnode . children . set ( slotIx , newChildParseNode ) ; return true ; } }
For a given parse node which we generated (or null).
For a given parse node which we generated ( or null ) .
// Not our immediate property - we propagate it down // Already invalidated // At least one case where this happens is for IdentifierExpression(identifiers,.) when we // add "arguments" to the expression.  // Some parselets do not generate a parse node - rather they just propagate up the nested parselets // value.  We'll skip passed these parselets during the generation. // This parsenode was optimized into a String so we can't do any incremental updates // If we have an "*" operators, see if we can propagate the change to a child. // This checks the "*"'s recursively down the tree to see which parselet produces this property // We are given a property change for a node we don't know about - return an error so we try the next choice // GenerateError... // If the parent node has already been invalidated, we should not need to create the children just to maintain // a ref point, since the parent will get entirely regenerated anyway. // Used to just use "value" here for the child parse node but that omits spacing // Right now, we are just replacing the value.  We could potentially try to merge the values to // preserve comments in the whitespace or something like that.  Possibly this should be a hook // on the parent or child parselet so it gets to merge updated parse nodes together? //parentParseNode.replace(oldChildParseNode, newChildParseNode, childParselet, slotIx);