OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. |
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> | 5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> |
6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | 6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> |
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) | 7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) |
8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. | 8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
9 * Copyright (C) 2012 Intel Corporation. All rights reserved. | 9 * Copyright (C) 2012 Intel Corporation. All rights reserved. |
10 * | 10 * |
(...skipping 2394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2405 if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) | 2405 if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) |
2406 return false; | 2406 return false; |
2407 return parseGridAreaShorthand(important); | 2407 return parseGridAreaShorthand(important); |
2408 | 2408 |
2409 case CSSPropertyGridTemplateAreas: | 2409 case CSSPropertyGridTemplateAreas: |
2410 if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) | 2410 if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) |
2411 return false; | 2411 return false; |
2412 parsedValue = parseGridTemplateAreas(); | 2412 parsedValue = parseGridTemplateAreas(); |
2413 break; | 2413 break; |
2414 | 2414 |
2415 case CSSPropertyGridTemplate: | |
2416 if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) | |
2417 return false; | |
2418 return parseGridTemplateShorthand(important); | |
2419 | |
2415 case CSSPropertyWebkitMarginCollapse: { | 2420 case CSSPropertyWebkitMarginCollapse: { |
2416 if (num == 1) { | 2421 if (num == 1) { |
2417 ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse); | 2422 ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse); |
2418 if (!parseValue(webkitMarginCollapseShorthand().properties()[0], imp ortant)) | 2423 if (!parseValue(webkitMarginCollapseShorthand().properties()[0], imp ortant)) |
2419 return false; | 2424 return false; |
2420 CSSValue* value = m_parsedProperties.last().value(); | 2425 CSSValue* value = m_parsedProperties.last().value(); |
2421 addProperty(webkitMarginCollapseShorthand().properties()[1], value, important); | 2426 addProperty(webkitMarginCollapseShorthand().properties()[1], value, important); |
2422 return true; | 2427 return true; |
2423 } | 2428 } |
2424 else if (num == 2) { | 2429 else if (num == 2) { |
(...skipping 2168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4593 return false; | 4598 return false; |
4594 } else { | 4599 } else { |
4595 endValue = gridMissingGridPositionValue(startValue.get()); | 4600 endValue = gridMissingGridPositionValue(startValue.get()); |
4596 } | 4601 } |
4597 | 4602 |
4598 addProperty(shorthand.properties()[0], startValue, important); | 4603 addProperty(shorthand.properties()[0], startValue, important); |
4599 addProperty(shorthand.properties()[1], endValue, important); | 4604 addProperty(shorthand.properties()[1], endValue, important); |
4600 return true; | 4605 return true; |
4601 } | 4606 } |
4602 | 4607 |
4608 bool BisonCSSParser::parseGridTemplateShorthand(bool important) | |
4609 { | |
4610 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | |
4611 | |
4612 ShorthandScope scope(this, CSSPropertyGridTemplate); | |
4613 const StylePropertyShorthand& shorthand = gridTemplateShorthand(); | |
4614 ASSERT_UNUSED(shorthand, shorthand.length() == 3); | |
Julien - ping for review
2014/02/21 20:04:50
ASSERT(gridTemplateShorthand().length() == 3) ?
| |
4615 | |
4616 if (!m_valueList->current()) | |
4617 return false; | |
4618 | |
4619 RefPtr<CSSValue> columnsValue; | |
4620 RefPtr<CSSValue> rowsValue; | |
4621 RefPtr<CSSValue> areasValue; | |
4622 NamedGridAreaMap gridAreaMap; | |
4623 size_t areaRowCount = 0; | |
4624 size_t areaColumnCount = 0; | |
4625 size_t numberOfClauses = 1; | |
Julien - ping for review
2014/02/21 20:04:50
This really should be a state, not a plain int. Yo
| |
4626 bool seenTemplateAreas = false; | |
4627 bool seenTrackSizeOrRepeat = false; | |
Julien - ping for review
2014/02/21 20:04:50
Per our style guide, this should be hasSeenTrackSi
| |
4628 | |
4629 RefPtr<CSSValueList> values = CSSValueList::createSpaceSeparated(); | |
4630 | |
4631 while (m_valueList->current()) { | |
4632 if (isForwardSlashOperator(m_valueList->current())) { | |
4633 // Slash not allowed in the second clause. Two clauses are required if slash used. | |
4634 if (++numberOfClauses > 2 || !m_valueList->next()) | |
4635 return false; | |
4636 if (values->length() > 0) | |
4637 columnsValue = values.release(); | |
4638 else | |
4639 columnsValue = cssValuePool().createIdentifierValue(CSSValueNone ); | |
4640 values = CSSValueList::createSpaceSeparated(); | |
4641 seenTrackSizeOrRepeat = false; | |
4642 } | |
4643 | |
4644 if (m_valueList->current()->id == CSSValueNone) { | |
4645 if (seenTemplateAreas) | |
4646 return false; // The 'none' value is not allowed in complex form . | |
4647 if (seenTrackSizeOrRepeat) | |
4648 return false; // The 'none' value is not allowed as part of a tr ack-size list. | |
4649 if (m_valueList->next()) { | |
4650 if (!isForwardSlashOperator(m_valueList->current())) | |
4651 return false; | |
4652 continue; | |
4653 } | |
4654 break; | |
4655 } | |
4656 | |
4657 // Handle leading <ident>*. | |
Julien - ping for review
2014/02/21 20:04:50
Let's be precise here. First the specification cal
| |
4658 if (m_valueList->current()->unit == CSSParserValue::ValueList) | |
4659 parseGridLineNames(m_valueList.get(), *values); | |
4660 | |
4661 // Handle a template-area's row. | |
4662 if (m_valueList->current() && m_valueList->current()->unit == CSSPrimiti veValue::CSS_STRING) { | |
4663 if (!parseGridTemplateAreasRow(gridAreaMap, areaRowCount, areaColumn Count)) | |
4664 return false; | |
4665 if (!areaRowCount && seenTrackSizeOrRepeat) | |
4666 return false; // No TrackSize allowed before the area's first ro w definition. | |
4667 ++areaRowCount; | |
4668 seenTemplateAreas = true; | |
4669 } | |
4670 | |
4671 // Handle template-{columns/rows}'s track-size, repeat or auto. | |
Julien - ping for review
2014/02/21 20:04:50
I am concerned by that. We have now effectively du
| |
4672 if (m_valueList->current() && m_valueList->current()->unit == CSSParserV alue::Function && equalIgnoringCase(m_valueList->current()->function->name, "rep eat(")) { | |
4673 if (seenTemplateAreas) | |
4674 return false; // Not allowed for template-row in complex form. | |
4675 if (!parseGridTrackRepeatFunction(*values)) | |
4676 return false; | |
4677 seenTrackSizeOrRepeat = true; | |
4678 } else if (m_valueList->current() && m_valueList->current()->unit != CSS ParserValue::ValueList && m_valueList->current()->unit != CSSPrimitiveValue::CSS _STRING) { | |
4679 RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList); | |
4680 if (!value) | |
4681 return false; | |
4682 values->append(value); | |
4683 seenTrackSizeOrRepeat = true; | |
4684 } else { | |
4685 if (!seenTemplateAreas) | |
4686 return false; // track-size mandatory in template-columns, "auto " otherwise. | |
4687 values->append(cssValuePool().createIdentifierValue(CSSValueAuto)); | |
4688 } | |
4689 | |
4690 // This will handle the trailing <ident>* in the grammar. | |
4691 if (m_valueList->current() && m_valueList->current()->unit == CSSParserV alue::ValueList) { | |
4692 parseGridLineNames(m_valueList.get(), *values); | |
4693 if (m_valueList->current() && m_valueList->current()->unit == CSSPar serValue::ValueList) { | |
4694 if (!seenTemplateAreas) | |
4695 return false; | |
4696 // Concat the last row's <ident>* with the new row's line name. | |
4697 parseGridLineNames(m_valueList.get(), *values, static_cast<CSSGr idLineNamesValue*>(values->item(values->length() - 1))); | |
4698 } | |
4699 if (seenTemplateAreas && m_valueList->current() && m_valueList->curr ent()->unit != CSSPrimitiveValue::CSS_STRING) | |
4700 return false; // area string mandatory (if additional elements) after line-name in complex form. | |
4701 } | |
4702 } | |
4703 | |
4704 // Handle template-areas property value. | |
4705 if (areaRowCount > 0) | |
4706 areasValue = CSSGridTemplateAreasValue::create(gridAreaMap, areaRowCount , areaColumnCount); | |
4707 else | |
4708 areasValue = cssValuePool().createIdentifierValue(CSSValueNone); | |
4709 | |
4710 // Handle template-columns property value. | |
4711 if (numberOfClauses == 1) { | |
4712 if (!areaRowCount && values->length() > 0) | |
4713 return false; | |
4714 columnsValue = cssValuePool().createIdentifierValue(CSSValueNone); | |
4715 } | |
4716 | |
4717 // Handle template-rows property value. | |
4718 if (values->length() > 0) | |
4719 rowsValue = values.release(); | |
4720 else if (areaRowCount > 0) | |
4721 return false; | |
4722 else | |
4723 rowsValue = cssValuePool().createIdentifierValue(CSSValueNone); | |
4724 | |
4725 addProperty(CSSPropertyGridTemplateColumns, columnsValue, important); | |
4726 addProperty(CSSPropertyGridTemplateRows, rowsValue, important); | |
4727 addProperty(CSSPropertyGridTemplateAreas, areasValue, important); | |
4728 | |
4729 return true; | |
4730 } | |
4731 | |
4603 bool BisonCSSParser::parseGridAreaShorthand(bool important) | 4732 bool BisonCSSParser::parseGridAreaShorthand(bool important) |
4604 { | 4733 { |
4605 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 4734 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
4606 | 4735 |
4607 ShorthandScope scope(this, CSSPropertyGridArea); | 4736 ShorthandScope scope(this, CSSPropertyGridArea); |
4608 const StylePropertyShorthand& shorthand = gridAreaShorthand(); | 4737 const StylePropertyShorthand& shorthand = gridAreaShorthand(); |
4609 ASSERT_UNUSED(shorthand, shorthand.length() == 4); | 4738 ASSERT_UNUSED(shorthand, shorthand.length() == 4); |
4610 | 4739 |
4611 RefPtr<CSSValue> rowStartValue = parseGridPosition(); | 4740 RefPtr<CSSValue> rowStartValue = parseGridPosition(); |
4612 if (!rowStartValue) | 4741 if (!rowStartValue) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4648 if (!isForwardSlashOperator(m_valueList->current())) | 4777 if (!isForwardSlashOperator(m_valueList->current())) |
4649 return false; | 4778 return false; |
4650 | 4779 |
4651 if (!m_valueList->next()) | 4780 if (!m_valueList->next()) |
4652 return false; | 4781 return false; |
4653 | 4782 |
4654 property = parseGridPosition(); | 4783 property = parseGridPosition(); |
4655 return true; | 4784 return true; |
4656 } | 4785 } |
4657 | 4786 |
4658 void BisonCSSParser::parseGridLineNames(CSSParserValueList* parserValueList, CSS ValueList& valueList) | 4787 void BisonCSSParser::parseGridLineNames(CSSParserValueList* parserValueList, CSS ValueList& valueList, CSSGridLineNamesValue* lineNamesToConcat) |
4659 { | 4788 { |
4660 ASSERT(parserValueList->current() && parserValueList->current()->unit == CSS ParserValue::ValueList); | 4789 ASSERT(parserValueList->current() && parserValueList->current()->unit == CSS ParserValue::ValueList); |
4661 | 4790 |
4662 CSSParserValueList* identList = parserValueList->current()->valueList; | 4791 CSSParserValueList* identList = parserValueList->current()->valueList; |
4663 if (!identList->size()) { | 4792 if (!identList->size()) { |
4664 parserValueList->next(); | 4793 parserValueList->next(); |
4665 return; | 4794 return; |
4666 } | 4795 } |
4667 | 4796 |
4668 RefPtrWillBeRawPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue: :create(); | 4797 RefPtr<CSSGridLineNamesValue> lineNames = lineNamesToConcat ? lineNamesToCon cat : CSSGridLineNamesValue::create(); |
4669 while (CSSParserValue* identValue = identList->current()) { | 4798 while (CSSParserValue* identValue = identList->current()) { |
4670 ASSERT(identValue->unit == CSSPrimitiveValue::CSS_IDENT); | 4799 ASSERT(identValue->unit == CSSPrimitiveValue::CSS_IDENT); |
4671 RefPtrWillBeRawPtr<CSSPrimitiveValue> lineName = createPrimitiveStringVa lue(identValue); | 4800 RefPtrWillBeRawPtr<CSSPrimitiveValue> lineName = createPrimitiveStringVa lue(identValue); |
4672 lineNames->append(lineName.release()); | 4801 lineNames->append(lineName.release()); |
4673 identList->next(); | 4802 identList->next(); |
4674 } | 4803 } |
4675 valueList.append(lineNames.release()); | 4804 if (!lineNamesToConcat) |
4805 valueList.append(lineNames.release()); | |
4676 | 4806 |
4677 parserValueList->next(); | 4807 parserValueList->next(); |
4678 } | 4808 } |
4679 | 4809 |
4680 bool BisonCSSParser::parseGridTrackList(CSSPropertyID propId, bool important) | 4810 bool BisonCSSParser::parseGridTrackList(CSSPropertyID propId, bool important) |
4681 { | 4811 { |
4682 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 4812 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
4683 | 4813 |
4684 CSSParserValue* value = m_valueList->current(); | 4814 CSSParserValue* value = m_valueList->current(); |
4685 if (value->id == CSSValueNone) { | 4815 if (value->id == CSSValueNone) { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4810 | 4940 |
4811 return cssValuePool().createValue(flexValue, CSSPrimitiveValue::CSS_FR); | 4941 return cssValuePool().createValue(flexValue, CSSPrimitiveValue::CSS_FR); |
4812 } | 4942 } |
4813 | 4943 |
4814 if (!validUnit(currentValue, FNonNeg | FLength | FPercent)) | 4944 if (!validUnit(currentValue, FNonNeg | FLength | FPercent)) |
4815 return 0; | 4945 return 0; |
4816 | 4946 |
4817 return createPrimitiveNumericValue(currentValue); | 4947 return createPrimitiveNumericValue(currentValue); |
4818 } | 4948 } |
4819 | 4949 |
4950 bool BisonCSSParser::parseGridTemplateAreasRow(NamedGridAreaMap& gridAreaMap, co nst size_t rowCount, size_t& columnCount) | |
4951 { | |
4952 CSSParserValue* currentValue = m_valueList->current(); | |
4953 if (!currentValue || currentValue->unit != CSSPrimitiveValue::CSS_STRING) | |
4954 return false; | |
4955 | |
4956 String gridRowNames = currentValue->string; | |
4957 if (!gridRowNames.length()) | |
4958 return false; | |
4959 | |
4960 Vector<String> columnNames; | |
4961 gridRowNames.split(' ', columnNames); | |
4962 | |
4963 if (!columnCount) { | |
4964 columnCount = columnNames.size(); | |
4965 ASSERT(columnCount); | |
4966 } else if (columnCount != columnNames.size()) { | |
4967 // The declaration is invalid is all the rows don't have the number of c olumns. | |
4968 return false; | |
4969 } | |
4970 | |
4971 for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) { | |
4972 const String& gridAreaName = columnNames[currentCol]; | |
4973 | |
4974 // Unamed areas are always valid (we consider them to be 1x1). | |
4975 if (gridAreaName == ".") | |
4976 continue; | |
4977 | |
4978 // We handle several grid areas with the same name at once to simplify t he validation code. | |
4979 size_t lookAheadCol; | |
4980 for (lookAheadCol = currentCol; lookAheadCol < (columnCount - 1); ++look AheadCol) { | |
4981 if (columnNames[lookAheadCol + 1] != gridAreaName) | |
4982 break; | |
4983 } | |
4984 | |
4985 NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName); | |
4986 if (gridAreaIt == gridAreaMap.end()) { | |
4987 gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowC ount), GridSpan(currentCol, lookAheadCol))); | |
4988 } else { | |
4989 GridCoordinate& gridCoordinate = gridAreaIt->value; | |
4990 | |
4991 // The following checks test that the grid area is a single filled-i n rectangle. | |
4992 // 1. The new row is adjacent to the previously parsed row. | |
4993 if (rowCount != gridCoordinate.rows.initialPositionIndex + 1) | |
4994 return false; | |
4995 | |
4996 // 2. The new area starts at the same position as the previously par sed area. | |
4997 if (currentCol != gridCoordinate.columns.initialPositionIndex) | |
4998 return false; | |
4999 | |
5000 // 3. The new area ends at the same position as the previously parse d area. | |
5001 if (lookAheadCol != gridCoordinate.columns.finalPositionIndex) | |
5002 return false; | |
5003 | |
5004 ++gridCoordinate.rows.finalPositionIndex; | |
5005 } | |
5006 currentCol = lookAheadCol; | |
5007 } | |
5008 | |
5009 m_valueList->next(); | |
5010 return true; | |
5011 } | |
5012 | |
4820 PassRefPtr<CSSValue> BisonCSSParser::parseGridTemplateAreas() | 5013 PassRefPtr<CSSValue> BisonCSSParser::parseGridTemplateAreas() |
4821 { | 5014 { |
4822 NamedGridAreaMap gridAreaMap; | 5015 NamedGridAreaMap gridAreaMap; |
4823 size_t rowCount = 0; | 5016 size_t rowCount = 0; |
4824 size_t columnCount = 0; | 5017 size_t columnCount = 0; |
4825 | 5018 |
4826 while (CSSParserValue* currentValue = m_valueList->current()) { | 5019 while (m_valueList->current()) { |
4827 if (currentValue->unit != CSSPrimitiveValue::CSS_STRING) | 5020 if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount)) |
4828 return 0; | 5021 return 0; |
4829 | |
4830 String gridRowNames = currentValue->string; | |
4831 if (!gridRowNames.length()) | |
4832 return 0; | |
4833 | |
4834 Vector<String> columnNames; | |
4835 gridRowNames.split(' ', columnNames); | |
4836 | |
4837 if (!columnCount) { | |
4838 columnCount = columnNames.size(); | |
4839 ASSERT(columnCount); | |
4840 } else if (columnCount != columnNames.size()) { | |
4841 // The declaration is invalid is all the rows don't have the number of columns. | |
4842 return 0; | |
4843 } | |
4844 | |
4845 for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) { | |
4846 const String& gridAreaName = columnNames[currentCol]; | |
4847 | |
4848 // Unamed areas are always valid (we consider them to be 1x1). | |
4849 if (gridAreaName == ".") | |
4850 continue; | |
4851 | |
4852 // We handle several grid areas with the same name at once to simpli fy the validation code. | |
4853 size_t lookAheadCol; | |
4854 for (lookAheadCol = currentCol; lookAheadCol < (columnCount - 1); ++ lookAheadCol) { | |
4855 if (columnNames[lookAheadCol + 1] != gridAreaName) | |
4856 break; | |
4857 } | |
4858 | |
4859 NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaNam e); | |
4860 if (gridAreaIt == gridAreaMap.end()) { | |
4861 gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentCol, lookAheadCol))); | |
4862 } else { | |
4863 GridCoordinate& gridCoordinate = gridAreaIt->value; | |
4864 | |
4865 // The following checks test that the grid area is a single fill ed-in rectangle. | |
4866 // 1. The new row is adjacent to the previously parsed row. | |
4867 if (rowCount != gridCoordinate.rows.initialPositionIndex + 1) | |
4868 return 0; | |
4869 | |
4870 // 2. The new area starts at the same position as the previously parsed area. | |
4871 if (currentCol != gridCoordinate.columns.initialPositionIndex) | |
4872 return 0; | |
4873 | |
4874 // 3. The new area ends at the same position as the previously p arsed area. | |
4875 if (lookAheadCol != gridCoordinate.columns.finalPositionIndex) | |
4876 return 0; | |
4877 | |
4878 ++gridCoordinate.rows.finalPositionIndex; | |
4879 } | |
4880 currentCol = lookAheadCol; | |
4881 } | |
4882 | |
4883 ++rowCount; | 5022 ++rowCount; |
4884 m_valueList->next(); | |
4885 } | 5023 } |
4886 | 5024 |
4887 if (!rowCount || !columnCount) | 5025 if (!rowCount || !columnCount) |
4888 return 0; | 5026 return 0; |
4889 | 5027 |
4890 return CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount) ; | 5028 return CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount) ; |
4891 } | 5029 } |
4892 | 5030 |
4893 PassRefPtr<CSSValue> BisonCSSParser::parseCounterContent(CSSParserValueList* arg s, bool counters) | 5031 PassRefPtr<CSSValue> BisonCSSParser::parseCounterContent(CSSParserValueList* arg s, bool counters) |
4894 { | 5032 { |
(...skipping 5201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10096 { | 10234 { |
10097 // The tokenizer checks for the construct of an+b. | 10235 // The tokenizer checks for the construct of an+b. |
10098 // However, since the {ident} rule precedes the {nth} rule, some of those | 10236 // However, since the {ident} rule precedes the {nth} rule, some of those |
10099 // tokens are identified as string literal. Furthermore we need to accept | 10237 // tokens are identified as string literal. Furthermore we need to accept |
10100 // "odd" and "even" which does not match to an+b. | 10238 // "odd" and "even" which does not match to an+b. |
10101 return equalIgnoringCase(token, "odd") || equalIgnoringCase(token, "even") | 10239 return equalIgnoringCase(token, "odd") || equalIgnoringCase(token, "even") |
10102 || equalIgnoringCase(token, "n") || equalIgnoringCase(token, "-n"); | 10240 || equalIgnoringCase(token, "n") || equalIgnoringCase(token, "-n"); |
10103 } | 10241 } |
10104 | 10242 |
10105 } | 10243 } |
OLD | NEW |