%{ // // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #include "pxr/pxr.h" #include "pxr/base/arch/fileSystem.h" #include "pxr/base/tf/stringUtils.h" #include "pxr/usd/sdf/textParserContext.h" #include "pxr/usd/sdf/parserHelpers.h" // Token table from yacc file #include "textFileFormat.tab.h" #ifndef fileno #define fileno(fd) ArchFileNo(fd) #endif #ifndef isatty #define isatty(fd) ArchFileIsaTTY(fd) #endif using std::map; using std::vector; PXR_NAMESPACE_USING_DIRECTIVE #define YYSTYPE Sdf_ParserHelpers::Value // As a pure parser, we must define the following #define YY_DECL int textFileFormatYylex(YYSTYPE *yylval_param, yyscan_t yyscanner) // The context object will be used to store global state for the parser. #define YY_EXTRA_TYPE Sdf_TextParserContext * %} /* Configuration options for flex */ %option noyywrap %option nounput %option reentrant %option bison-bridge /* States */ %x SLASHTERIX_COMMENT %% /* skip over whitespace and comments */ /* handle the first line # comment specially, since it contains the magic token */ [[:blank:]]+ {} "#"[^\r\n]* { if (yyextra->menvaLineNo == 1) { (*yylval_param) = std::string(yytext, yyleng); return TOK_MAGIC; } } "//"[^\r\n]* {} "/*" BEGIN SLASHTERIX_COMMENT ; .|\n|\r ; "*/" BEGIN INITIAL ; /* newline is returned as TOK_NL * Note that newlines embedded in quoted strings and tuples are counted * as part of the token and do NOT emit a separate TOK_NL. */ ((\r\n)|\r|\n) { yyextra->menvaLineNo++; return TOK_NL; } /* literal keywords. we return the yytext so that the yacc grammar can make use of it. */ "add" { (*yylval_param) = std::string(yytext, yyleng); return TOK_ADD; } "append" { (*yylval_param) = std::string(yytext, yyleng); return TOK_APPEND; } "class" { (*yylval_param) = std::string(yytext, yyleng); return TOK_CLASS; } "config" { (*yylval_param) = std::string(yytext, yyleng); return TOK_CONFIG; } "connect" { (*yylval_param) = std::string(yytext, yyleng); return TOK_CONNECT; } "custom" { (*yylval_param) = std::string(yytext, yyleng); return TOK_CUSTOM; } "customData" { (*yylval_param) = std::string(yytext, yyleng); return TOK_CUSTOMDATA; } "default" { (*yylval_param) = std::string(yytext, yyleng); return TOK_DEFAULT; } "def" { (*yylval_param) = std::string(yytext, yyleng); return TOK_DEF; } "delete" { (*yylval_param) = std::string(yytext, yyleng); return TOK_DELETE; } "dictionary" { (*yylval_param) = std::string(yytext, yyleng); return TOK_DICTIONARY; } "displayUnit" { (*yylval_param) = std::string(yytext, yyleng); return TOK_DISPLAYUNIT; } "doc" { (*yylval_param) = std::string(yytext, yyleng); return TOK_DOC; } "inherits" { (*yylval_param) = std::string(yytext, yyleng); return TOK_INHERITS; } "kind" { (*yylval_param) = std::string(yytext, yyleng); return TOK_KIND; } "nameChildren" { (*yylval_param) = std::string(yytext, yyleng); return TOK_NAMECHILDREN; } "None" { (*yylval_param) = std::string(yytext, yyleng); return TOK_NONE; } "offset" { (*yylval_param) = std::string(yytext, yyleng); return TOK_OFFSET; } "over" { (*yylval_param) = std::string(yytext, yyleng); return TOK_OVER; } "payload" { (*yylval_param) = std::string(yytext, yyleng); return TOK_PAYLOAD; } "permission" { (*yylval_param) = std::string(yytext, yyleng); return TOK_PERMISSION; } "prefixSubstitutions" { (*yylval_param) = std::string(yytext, yyleng); return TOK_PREFIX_SUBSTITUTIONS; } "prepend" { (*yylval_param) = std::string(yytext, yyleng); return TOK_PREPEND; } "properties" { (*yylval_param) = std::string(yytext, yyleng); return TOK_PROPERTIES; } "references" { (*yylval_param) = std::string(yytext, yyleng); return TOK_REFERENCES; } "relocates" { (*yylval_param) = std::string(yytext, yyleng); return TOK_RELOCATES; } "rel" { (*yylval_param) = std::string(yytext, yyleng); return TOK_REL; } "reorder" { (*yylval_param) = std::string(yytext, yyleng); return TOK_REORDER; } "rootPrims" { (*yylval_param) = std::string(yytext, yyleng); return TOK_ROOTPRIMS; } "scale" { (*yylval_param) = std::string(yytext, yyleng); return TOK_SCALE; } "subLayers" { (*yylval_param) = std::string(yytext, yyleng); return TOK_SUBLAYERS; } "suffixSubstitutions" { (*yylval_param) = std::string(yytext, yyleng); return TOK_SUFFIX_SUBSTITUTIONS; } "specializes" { (*yylval_param) = std::string(yytext, yyleng); return TOK_SPECIALIZES; } "symmetryArguments" { (*yylval_param) = std::string(yytext, yyleng); return TOK_SYMMETRYARGUMENTS; } "symmetryFunction" { (*yylval_param) = std::string(yytext, yyleng); return TOK_SYMMETRYFUNCTION; } "timeSamples" { (*yylval_param) = std::string(yytext, yyleng); return TOK_TIME_SAMPLES; } "uniform" { (*yylval_param) = std::string(yytext, yyleng); return TOK_UNIFORM; } "variantSet" { (*yylval_param) = std::string(yytext, yyleng); return TOK_VARIANTSET; } "variantSets" { (*yylval_param) = std::string(yytext, yyleng); return TOK_VARIANTSETS; } "variants" { (*yylval_param) = std::string(yytext, yyleng); return TOK_VARIANTS; } "varying" { (*yylval_param) = std::string(yytext, yyleng); return TOK_VARYING; } /* unquoted C/Python identifier */ [[:alpha:]_][[:alnum:]_]* { (*yylval_param) = std::string(yytext, yyleng); return TOK_IDENTIFIER; } /* unquoted C++ namespaced identifier -- see bug 10775 */ [[:alpha:]_][[:alnum:]_]*(::[[:alpha:]_][[:alnum:]_]*)+ { (*yylval_param) = std::string(yytext, yyleng); return TOK_CXX_NAMESPACED_IDENTIFIER; } /* unquoted namespaced identifier. matches any number of colon * delimited C/Python identifiers */ [[:alpha:]_][[:alnum:]_]*(:[[:alpha:]_][[:alnum:]_]*)+ { (*yylval_param) = std::string(yytext, yyleng); return TOK_NAMESPACED_IDENTIFIER; } /* scene paths */ \<[^\<\>\r\n]*\> { (*yylval_param) = Sdf_EvalQuotedString(yytext, yyleng, 1); return TOK_PATHREF; } /* Single '@'-delimited asset references */ @([^[:cntrl:]@]+)?@ { (*yylval_param) = Sdf_EvalAssetPath(yytext, yyleng, /* tripleDelimited = */ false); return TOK_ASSETREF; } /* Triple '@'-delimited asset references. */ @@@(([^[:cntrl:]@]|@{1,2}[^@]|\\@@@)+)?(@{0,2})@@@ { (*yylval_param) = Sdf_EvalAssetPath(yytext, yyleng, /* tripleDelimited = */ true); return TOK_ASSETREF; } /* Singly quoted, single line strings with escapes. Note: we handle empty singly quoted strings below, to disambiguate them from the beginning of triply-quoted strings. Ex: "Foo \"foo\"" */ '([^'\r\n]|(\\.))+' | /* ' //<- unfreak out coloring code */ \"([^"\r\n]|(\\.))+\" { /* " //<- unfreak out coloring code */ (*yylval_param) = Sdf_EvalQuotedString(yytext, yyleng, 1); return TOK_STRING; } /* Empty singly quoted strings that aren't the beginning of a triply-quoted string. */ ''/[^'] { /* ' // <- keep syntax coloring from freaking out */ (*yylval_param) = std::string(); return TOK_STRING; } \"\"/[^"] { (*yylval_param) = std::string(); return TOK_STRING; } /* Triply quoted, multi-line strings with escapes. Ex: """A\n\"B\"\nC""" */ '''([^']|(\\.)|('{1,2}[^']))*''' | /* ' //<- unfreak out coloring code */ \"\"\"([^"]|(\\.)|(\"{1,2}[^"]))*\"\"\" { /* " //<- unfreak out coloring code */ unsigned int numlines = 0; (*yylval_param) = Sdf_EvalQuotedString(yytext, yyleng, 3, &numlines); yyextra->menvaLineNo += numlines; return TOK_STRING; } /* Super special case for negative 0. We have to store this as a double to * preserve the sign. There is no negative zero integral value, and we * don't know at this point what the final stored type will be. */ -0 { (*yylval_param) = double(-0.0); return TOK_NUMBER; } /* Positive integers: store as uint64_t if in range, otherwise double. */ [[:digit:]]+ { bool outOfRange = false; (*yylval_param) = TfStringToUInt64(yytext, &outOfRange); if (outOfRange) { TF_WARN("Integer literal '%s' on line %d%s%s out of range, parsing " "as double. Consider exponential notation for large " "floating point values.", yytext, yyextra->menvaLineNo, yyextra->fileContext.empty() ? "" : " in file ", yyextra->fileContext.empty() ? "" : yyextra->fileContext.c_str()); (*yylval_param) = TfStringToDouble(yytext); } return TOK_NUMBER; } /* Negative integers: store as long. */ -[[:digit:]]+ { bool outOfRange = false; (*yylval_param) = TfStringToInt64(yytext, &outOfRange); if (outOfRange) { TF_WARN("Integer literal '%s' on line %d%s%s out of range, parsing " "as double. Consider exponential notation for large " "floating point values.", yytext, yyextra->menvaLineNo, yyextra->fileContext.empty() ? "" : " in file ", yyextra->fileContext.empty() ? "" : yyextra->fileContext.c_str()); (*yylval_param) = TfStringToDouble(yytext); } return TOK_NUMBER; } /* Numbers with decimal places or exponents: store as double. */ -?[[:digit:]]+(\.[[:digit:]]*)?([eE][+\-]?[[:digit:]]+)? | -?\.[[:digit:]]+([eE][+\-]?[[:digit:]]+)? { (*yylval_param) = TfStringToDouble(yytext); return TOK_NUMBER; } /* regexps for negative infinity. we don't handle inf and nan here * because they look like identifiers. we handle them in parser where * we have the additional context we need to distinguish them from * identifiers. */ -inf { (*yylval_param) = -std::numeric_limits::infinity(); return TOK_NUMBER; } /* various single-character punctuation. return the character * itself as the token. */ [=,:;\$\.\[\]\(\){}&@-] { return yytext[0]; } /* the default rule is to ECHO any unmatched character. by returning a * token that the parser does not know how to handle these become syntax * errors instead. */ <*>.|\\n { return TOK_SYNTAX_ERROR; } %%