Best Atoum code snippet using parser
scannerc.go
Source:scannerc.go
...13// The process of transforming a YAML stream into a sequence of events is14// divided on two steps: Scanning and Parsing.15//16// The Scanner transforms the input stream into a sequence of tokens, while the17// parser transform the sequence of tokens produced by the Scanner into a18// sequence of parsing events.19//20// The Scanner is rather clever and complicated. The Parser, on the contrary,21// is a straightforward implementation of a recursive-descendant parser (or,22// LL(1) parser, as it is usually called).23//24// Actually there are two issues of Scanning that might be called "clever", the25// rest is quite straightforward. The issues are "block collection start" and26// "simple keys". Both issues are explained below in details.27//28// Here the Scanning step is explained and implemented. We start with the list29// of all the tokens produced by the Scanner together with short descriptions.30//31// Now, tokens:32//33// STREAM-START(encoding) # The stream start.34// STREAM-END # The stream end.35// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.36// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.37// DOCUMENT-START # '---'38// DOCUMENT-END # '...'39// BLOCK-SEQUENCE-START # Indentation increase denoting a block40// BLOCK-MAPPING-START # sequence or a block mapping.41// BLOCK-END # Indentation decrease.42// FLOW-SEQUENCE-START # '['43// FLOW-SEQUENCE-END # ']'44// BLOCK-SEQUENCE-START # '{'45// BLOCK-SEQUENCE-END # '}'46// BLOCK-ENTRY # '-'47// FLOW-ENTRY # ','48// KEY # '?' or nothing (simple keys).49// VALUE # ':'50// ALIAS(anchor) # '*anchor'51// ANCHOR(anchor) # '&anchor'52// TAG(handle,suffix) # '!handle!suffix'53// SCALAR(value,style) # A scalar.54//55// The following two tokens are "virtual" tokens denoting the beginning and the56// end of the stream:57//58// STREAM-START(encoding)59// STREAM-END60//61// We pass the information about the input stream encoding with the62// STREAM-START token.63//64// The next two tokens are responsible for tags:65//66// VERSION-DIRECTIVE(major,minor)67// TAG-DIRECTIVE(handle,prefix)68//69// Example:70//71// %YAML 1.172// %TAG ! !foo73// %TAG !yaml! tag:yaml.org,2002:74// ---75//76// The correspoding sequence of tokens:77//78// STREAM-START(utf-8)79// VERSION-DIRECTIVE(1,1)80// TAG-DIRECTIVE("!","!foo")81// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")82// DOCUMENT-START83// STREAM-END84//85// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole86// line.87//88// The document start and end indicators are represented by:89//90// DOCUMENT-START91// DOCUMENT-END92//93// Note that if a YAML stream contains an implicit document (without '---'94// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be95// produced.96//97// In the following examples, we present whole documents together with the98// produced tokens.99//100// 1. An implicit document:101//102// 'a scalar'103//104// Tokens:105//106// STREAM-START(utf-8)107// SCALAR("a scalar",single-quoted)108// STREAM-END109//110// 2. An explicit document:111//112// ---113// 'a scalar'114// ...115//116// Tokens:117//118// STREAM-START(utf-8)119// DOCUMENT-START120// SCALAR("a scalar",single-quoted)121// DOCUMENT-END122// STREAM-END123//124// 3. Several documents in a stream:125//126// 'a scalar'127// ---128// 'another scalar'129// ---130// 'yet another scalar'131//132// Tokens:133//134// STREAM-START(utf-8)135// SCALAR("a scalar",single-quoted)136// DOCUMENT-START137// SCALAR("another scalar",single-quoted)138// DOCUMENT-START139// SCALAR("yet another scalar",single-quoted)140// STREAM-END141//142// We have already introduced the SCALAR token above. The following tokens are143// used to describe aliases, anchors, tag, and scalars:144//145// ALIAS(anchor)146// ANCHOR(anchor)147// TAG(handle,suffix)148// SCALAR(value,style)149//150// The following series of examples illustrate the usage of these tokens:151//152// 1. A recursive sequence:153//154// &A [ *A ]155//156// Tokens:157//158// STREAM-START(utf-8)159// ANCHOR("A")160// FLOW-SEQUENCE-START161// ALIAS("A")162// FLOW-SEQUENCE-END163// STREAM-END164//165// 2. A tagged scalar:166//167// !!float "3.14" # A good approximation.168//169// Tokens:170//171// STREAM-START(utf-8)172// TAG("!!","float")173// SCALAR("3.14",double-quoted)174// STREAM-END175//176// 3. Various scalar styles:177//178// --- # Implicit empty plain scalars do not produce tokens.179// --- a plain scalar180// --- 'a single-quoted scalar'181// --- "a double-quoted scalar"182// --- |-183// a literal scalar184// --- >-185// a folded186// scalar187//188// Tokens:189//190// STREAM-START(utf-8)191// DOCUMENT-START192// DOCUMENT-START193// SCALAR("a plain scalar",plain)194// DOCUMENT-START195// SCALAR("a single-quoted scalar",single-quoted)196// DOCUMENT-START197// SCALAR("a double-quoted scalar",double-quoted)198// DOCUMENT-START199// SCALAR("a literal scalar",literal)200// DOCUMENT-START201// SCALAR("a folded scalar",folded)202// STREAM-END203//204// Now it's time to review collection-related tokens. We will start with205// flow collections:206//207// FLOW-SEQUENCE-START208// FLOW-SEQUENCE-END209// FLOW-MAPPING-START210// FLOW-MAPPING-END211// FLOW-ENTRY212// KEY213// VALUE214//215// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and216// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'217// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the218// indicators '?' and ':', which are used for denoting mapping keys and values,219// are represented by the KEY and VALUE tokens.220//221// The following examples show flow collections:222//223// 1. A flow sequence:224//225// [item 1, item 2, item 3]226//227// Tokens:228//229// STREAM-START(utf-8)230// FLOW-SEQUENCE-START231// SCALAR("item 1",plain)232// FLOW-ENTRY233// SCALAR("item 2",plain)234// FLOW-ENTRY235// SCALAR("item 3",plain)236// FLOW-SEQUENCE-END237// STREAM-END238//239// 2. A flow mapping:240//241// {242// a simple key: a value, # Note that the KEY token is produced.243// ? a complex key: another value,244// }245//246// Tokens:247//248// STREAM-START(utf-8)249// FLOW-MAPPING-START250// KEY251// SCALAR("a simple key",plain)252// VALUE253// SCALAR("a value",plain)254// FLOW-ENTRY255// KEY256// SCALAR("a complex key",plain)257// VALUE258// SCALAR("another value",plain)259// FLOW-ENTRY260// FLOW-MAPPING-END261// STREAM-END262//263// A simple key is a key which is not denoted by the '?' indicator. Note that264// the Scanner still produce the KEY token whenever it encounters a simple key.265//266// For scanning block collections, the following tokens are used (note that we267// repeat KEY and VALUE here):268//269// BLOCK-SEQUENCE-START270// BLOCK-MAPPING-START271// BLOCK-END272// BLOCK-ENTRY273// KEY274// VALUE275//276// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation277// increase that precedes a block collection (cf. the INDENT token in Python).278// The token BLOCK-END denote indentation decrease that ends a block collection279// (cf. the DEDENT token in Python). However YAML has some syntax pecularities280// that makes detections of these tokens more complex.281//282// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators283// '-', '?', and ':' correspondingly.284//285// The following examples show how the tokens BLOCK-SEQUENCE-START,286// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:287//288// 1. Block sequences:289//290// - item 1291// - item 2292// -293// - item 3.1294// - item 3.2295// -296// key 1: value 1297// key 2: value 2298//299// Tokens:300//301// STREAM-START(utf-8)302// BLOCK-SEQUENCE-START303// BLOCK-ENTRY304// SCALAR("item 1",plain)305// BLOCK-ENTRY306// SCALAR("item 2",plain)307// BLOCK-ENTRY308// BLOCK-SEQUENCE-START309// BLOCK-ENTRY310// SCALAR("item 3.1",plain)311// BLOCK-ENTRY312// SCALAR("item 3.2",plain)313// BLOCK-END314// BLOCK-ENTRY315// BLOCK-MAPPING-START316// KEY317// SCALAR("key 1",plain)318// VALUE319// SCALAR("value 1",plain)320// KEY321// SCALAR("key 2",plain)322// VALUE323// SCALAR("value 2",plain)324// BLOCK-END325// BLOCK-END326// STREAM-END327//328// 2. Block mappings:329//330// a simple key: a value # The KEY token is produced here.331// ? a complex key332// : another value333// a mapping:334// key 1: value 1335// key 2: value 2336// a sequence:337// - item 1338// - item 2339//340// Tokens:341//342// STREAM-START(utf-8)343// BLOCK-MAPPING-START344// KEY345// SCALAR("a simple key",plain)346// VALUE347// SCALAR("a value",plain)348// KEY349// SCALAR("a complex key",plain)350// VALUE351// SCALAR("another value",plain)352// KEY353// SCALAR("a mapping",plain)354// BLOCK-MAPPING-START355// KEY356// SCALAR("key 1",plain)357// VALUE358// SCALAR("value 1",plain)359// KEY360// SCALAR("key 2",plain)361// VALUE362// SCALAR("value 2",plain)363// BLOCK-END364// KEY365// SCALAR("a sequence",plain)366// VALUE367// BLOCK-SEQUENCE-START368// BLOCK-ENTRY369// SCALAR("item 1",plain)370// BLOCK-ENTRY371// SCALAR("item 2",plain)372// BLOCK-END373// BLOCK-END374// STREAM-END375//376// YAML does not always require to start a new block collection from a new377// line. If the current line contains only '-', '?', and ':' indicators, a new378// block collection may start at the current line. The following examples379// illustrate this case:380//381// 1. Collections in a sequence:382//383// - - item 1384// - item 2385// - key 1: value 1386// key 2: value 2387// - ? complex key388// : complex value389//390// Tokens:391//392// STREAM-START(utf-8)393// BLOCK-SEQUENCE-START394// BLOCK-ENTRY395// BLOCK-SEQUENCE-START396// BLOCK-ENTRY397// SCALAR("item 1",plain)398// BLOCK-ENTRY399// SCALAR("item 2",plain)400// BLOCK-END401// BLOCK-ENTRY402// BLOCK-MAPPING-START403// KEY404// SCALAR("key 1",plain)405// VALUE406// SCALAR("value 1",plain)407// KEY408// SCALAR("key 2",plain)409// VALUE410// SCALAR("value 2",plain)411// BLOCK-END412// BLOCK-ENTRY413// BLOCK-MAPPING-START414// KEY415// SCALAR("complex key")416// VALUE417// SCALAR("complex value")418// BLOCK-END419// BLOCK-END420// STREAM-END421//422// 2. Collections in a mapping:423//424// ? a sequence425// : - item 1426// - item 2427// ? a mapping428// : key 1: value 1429// key 2: value 2430//431// Tokens:432//433// STREAM-START(utf-8)434// BLOCK-MAPPING-START435// KEY436// SCALAR("a sequence",plain)437// VALUE438// BLOCK-SEQUENCE-START439// BLOCK-ENTRY440// SCALAR("item 1",plain)441// BLOCK-ENTRY442// SCALAR("item 2",plain)443// BLOCK-END444// KEY445// SCALAR("a mapping",plain)446// VALUE447// BLOCK-MAPPING-START448// KEY449// SCALAR("key 1",plain)450// VALUE451// SCALAR("value 1",plain)452// KEY453// SCALAR("key 2",plain)454// VALUE455// SCALAR("value 2",plain)456// BLOCK-END457// BLOCK-END458// STREAM-END459//460// YAML also permits non-indented sequences if they are included into a block461// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:462//463// key:464// - item 1 # BLOCK-SEQUENCE-START is NOT produced here.465// - item 2466//467// Tokens:468//469// STREAM-START(utf-8)470// BLOCK-MAPPING-START471// KEY472// SCALAR("key",plain)473// VALUE474// BLOCK-ENTRY475// SCALAR("item 1",plain)476// BLOCK-ENTRY477// SCALAR("item 2",plain)478// BLOCK-END479//480// Ensure that the buffer contains the required number of characters.481// Return true on success, false on failure (reader error or memory error).482func cache(parser *yaml_parser_t, length int) bool {483 // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B)484 return parser.unread >= length || yaml_parser_update_buffer(parser, length)485}486// Advance the buffer pointer.487func skip(parser *yaml_parser_t) {488 parser.mark.index++489 parser.mark.column++490 parser.unread--491 parser.buffer_pos += width(parser.buffer[parser.buffer_pos])492}493func skip_line(parser *yaml_parser_t) {494 if is_crlf(parser.buffer, parser.buffer_pos) {495 parser.mark.index += 2496 parser.mark.column = 0497 parser.mark.line++498 parser.unread -= 2499 parser.buffer_pos += 2500 } else if is_break(parser.buffer, parser.buffer_pos) {501 parser.mark.index++502 parser.mark.column = 0503 parser.mark.line++504 parser.unread--505 parser.buffer_pos += width(parser.buffer[parser.buffer_pos])506 }507}508// Copy a character to a string buffer and advance pointers.509func read(parser *yaml_parser_t, s []byte) []byte {510 w := width(parser.buffer[parser.buffer_pos])511 if w == 0 {512 panic("invalid character sequence")513 }514 if len(s) == 0 {515 s = make([]byte, 0, 32)516 }517 if w == 1 && len(s)+w <= cap(s) {518 s = s[:len(s)+1]519 s[len(s)-1] = parser.buffer[parser.buffer_pos]520 parser.buffer_pos++521 } else {522 s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)523 parser.buffer_pos += w524 }525 parser.mark.index++526 parser.mark.column++527 parser.unread--528 return s529}530// Copy a line break character to a string buffer and advance pointers.531func read_line(parser *yaml_parser_t, s []byte) []byte {532 buf := parser.buffer533 pos := parser.buffer_pos534 switch {535 case buf[pos] == '\r' && buf[pos+1] == '\n':536 // CR LF . LF537 s = append(s, '\n')538 parser.buffer_pos += 2539 parser.mark.index++540 parser.unread--541 case buf[pos] == '\r' || buf[pos] == '\n':542 // CR|LF . LF543 s = append(s, '\n')544 parser.buffer_pos += 1545 case buf[pos] == '\xC2' && buf[pos+1] == '\x85':546 // NEL . LF547 s = append(s, '\n')548 parser.buffer_pos += 2549 case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):550 // LS|PS . LS|PS551 s = append(s, buf[parser.buffer_pos:pos+3]...)552 parser.buffer_pos += 3553 default:554 return s555 }556 parser.mark.index++557 parser.mark.column = 0558 parser.mark.line++559 parser.unread--560 return s561}562// Get the next token.563func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {564 // Erase the token object.565 *token = yaml_token_t{} // [Go] Is this necessary?566 // No tokens after STREAM-END or error.567 if parser.stream_end_produced || parser.error != yaml_NO_ERROR {568 return true569 }570 // Ensure that the tokens queue contains enough tokens.571 if !parser.token_available {572 if !yaml_parser_fetch_more_tokens(parser) {573 return false574 }575 }576 // Fetch the next token from the queue.577 *token = parser.tokens[parser.tokens_head]578 parser.tokens_head++579 parser.tokens_parsed++580 parser.token_available = false581 if token.typ == yaml_STREAM_END_TOKEN {582 parser.stream_end_produced = true583 }584 return true585}586// Set the scanner error and return false.587func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool {588 parser.error = yaml_SCANNER_ERROR589 parser.context = context590 parser.context_mark = context_mark591 parser.problem = problem592 parser.problem_mark = parser.mark593 return false594}595func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool {596 context := "while parsing a tag"597 if directive {598 context = "while parsing a %TAG directive"599 }600 return yaml_parser_set_scanner_error(parser, context, context_mark, problem)601}602func trace(args ...interface{}) func() {603 pargs := append([]interface{}{"+++"}, args...)604 fmt.Println(pargs...)605 pargs = append([]interface{}{"---"}, args...)606 return func() { fmt.Println(pargs...) }607}608// Ensure that the tokens queue contains at least one token which can be609// returned to the Parser.610func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {611 // While we need more tokens to fetch, do it.612 for {613 // Check if we really need to fetch more tokens.614 need_more_tokens := false615 if parser.tokens_head == len(parser.tokens) {616 // Queue is empty.617 need_more_tokens = true618 } else {619 // Check if any potential simple key may occupy the head position.620 if !yaml_parser_stale_simple_keys(parser) {621 return false622 }623 for i := range parser.simple_keys {624 simple_key := &parser.simple_keys[i]625 if simple_key.possible && simple_key.token_number == parser.tokens_parsed {626 need_more_tokens = true627 break628 }629 }630 }631 // We are finished.632 if !need_more_tokens {633 break634 }635 // Fetch the next token.636 if !yaml_parser_fetch_next_token(parser) {637 return false638 }639 }640 parser.token_available = true641 return true642}643// The dispatcher for token fetchers.644func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {645 // Ensure that the buffer is initialized.646 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {647 return false648 }649 // Check if we just started scanning. Fetch STREAM-START then.650 if !parser.stream_start_produced {651 return yaml_parser_fetch_stream_start(parser)652 }653 // Eat whitespaces and comments until we reach the next token.654 if !yaml_parser_scan_to_next_token(parser) {655 return false656 }657 // Remove obsolete potential simple keys.658 if !yaml_parser_stale_simple_keys(parser) {659 return false660 }661 // Check the indentation level against the current column.662 if !yaml_parser_unroll_indent(parser, parser.mark.column) {663 return false664 }665 // Ensure that the buffer contains at least 4 characters. 4 is the length666 // of the longest indicators ('--- ' and '... ').667 if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {668 return false669 }670 // Is it the end of the stream?671 if is_z(parser.buffer, parser.buffer_pos) {672 return yaml_parser_fetch_stream_end(parser)673 }674 // Is it a directive?675 if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' {676 return yaml_parser_fetch_directive(parser)677 }678 buf := parser.buffer679 pos := parser.buffer_pos680 // Is it the document start indicator?681 if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) {682 return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN)683 }684 // Is it the document end indicator?685 if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) {686 return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)687 }688 // Is it the flow sequence start indicator?689 if buf[pos] == '[' {690 return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)691 }692 // Is it the flow mapping start indicator?693 if parser.buffer[parser.buffer_pos] == '{' {694 return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN)695 }696 // Is it the flow sequence end indicator?697 if parser.buffer[parser.buffer_pos] == ']' {698 return yaml_parser_fetch_flow_collection_end(parser,699 yaml_FLOW_SEQUENCE_END_TOKEN)700 }701 // Is it the flow mapping end indicator?702 if parser.buffer[parser.buffer_pos] == '}' {703 return yaml_parser_fetch_flow_collection_end(parser,704 yaml_FLOW_MAPPING_END_TOKEN)705 }706 // Is it the flow entry indicator?707 if parser.buffer[parser.buffer_pos] == ',' {708 return yaml_parser_fetch_flow_entry(parser)709 }710 // Is it the block entry indicator?711 if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) {712 return yaml_parser_fetch_block_entry(parser)713 }714 // Is it the key indicator?715 if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {716 return yaml_parser_fetch_key(parser)717 }718 // Is it the value indicator?719 if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {720 return yaml_parser_fetch_value(parser)721 }722 // Is it an alias?723 if parser.buffer[parser.buffer_pos] == '*' {724 return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN)725 }726 // Is it an anchor?727 if parser.buffer[parser.buffer_pos] == '&' {728 return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN)729 }730 // Is it a tag?731 if parser.buffer[parser.buffer_pos] == '!' {732 return yaml_parser_fetch_tag(parser)733 }734 // Is it a literal scalar?735 if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {736 return yaml_parser_fetch_block_scalar(parser, true)737 }738 // Is it a folded scalar?739 if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {740 return yaml_parser_fetch_block_scalar(parser, false)741 }742 // Is it a single-quoted scalar?743 if parser.buffer[parser.buffer_pos] == '\'' {744 return yaml_parser_fetch_flow_scalar(parser, true)745 }746 // Is it a double-quoted scalar?747 if parser.buffer[parser.buffer_pos] == '"' {748 return yaml_parser_fetch_flow_scalar(parser, false)749 }750 // Is it a plain scalar?751 //752 // A plain scalar may start with any non-blank characters except753 //754 // '-', '?', ':', ',', '[', ']', '{', '}',755 // '#', '&', '*', '!', '|', '>', '\'', '\"',756 // '%', '@', '`'.757 //758 // In the block context (and, for the '-' indicator, in the flow context759 // too), it may also start with the characters760 //761 // '-', '?', ':'762 //763 // if it is followed by a non-space character.764 //765 // The last rule is more restrictive than the specification requires.766 // [Go] Make this logic more reasonable.767 //switch parser.buffer[parser.buffer_pos] {768 //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':769 //}770 if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||771 parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||772 parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||773 parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||774 parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||775 parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||776 parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||777 parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||778 parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||779 parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||780 (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) ||781 (parser.flow_level == 0 &&782 (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&783 !is_blankz(parser.buffer, parser.buffer_pos+1)) {784 return yaml_parser_fetch_plain_scalar(parser)785 }786 // If we don't determine the token type so far, it is an error.787 return yaml_parser_set_scanner_error(parser,788 "while scanning for the next token", parser.mark,789 "found character that cannot start any token")790}791// Check the list of potential simple keys and remove the positions that792// cannot contain simple keys anymore.793func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool {794 // Check for a potential simple key for each flow level.795 for i := range parser.simple_keys {796 simple_key := &parser.simple_keys[i]797 // The specification requires that a simple key798 //799 // - is limited to a single line,800 // - is shorter than 1024 characters.801 if simple_key.possible && (simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index) {802 // Check if the potential simple key to be removed is required.803 if simple_key.required {804 return yaml_parser_set_scanner_error(parser,805 "while scanning a simple key", simple_key.mark,806 "could not find expected ':'")807 }808 simple_key.possible = false809 }810 }811 return true812}813// Check if a simple key may start at the current position and add it if814// needed.815func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {816 // A simple key is required at the current position if the scanner is in817 // the block context and the current column coincides with the indentation818 // level.819 required := parser.flow_level == 0 && parser.indent == parser.mark.column820 //821 // If the current position may start a simple key, save it.822 //823 if parser.simple_key_allowed {824 simple_key := yaml_simple_key_t{825 possible: true,826 required: required,827 token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),828 }829 simple_key.mark = parser.mark830 if !yaml_parser_remove_simple_key(parser) {831 return false832 }833 parser.simple_keys[len(parser.simple_keys)-1] = simple_key834 }835 return true836}837// Remove a potential simple key at the current flow level.838func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {839 i := len(parser.simple_keys) - 1840 if parser.simple_keys[i].possible {841 // If the key is required, it is an error.842 if parser.simple_keys[i].required {843 return yaml_parser_set_scanner_error(parser,844 "while scanning a simple key", parser.simple_keys[i].mark,845 "could not find expected ':'")846 }847 }848 // Remove the key from the stack.849 parser.simple_keys[i].possible = false850 return true851}852// Increase the flow level and resize the simple key list if needed.853func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {854 // Reset the simple key on the next level.855 parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})856 // Increase the flow level.857 parser.flow_level++858 return true859}860// Decrease the flow level.861func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {862 if parser.flow_level > 0 {863 parser.flow_level--864 parser.simple_keys = parser.simple_keys[:len(parser.simple_keys)-1]865 }866 return true867}868// Push the current indentation level to the stack and set the new level869// the current column is greater than the indentation level. In this case,870// append or insert the specified token into the token queue.871func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool {872 // In the flow context, do nothing.873 if parser.flow_level > 0 {874 return true875 }876 if parser.indent < column {877 // Push the current indentation level to the stack and set the new878 // indentation level.879 parser.indents = append(parser.indents, parser.indent)880 parser.indent = column881 // Create a token and insert it into the queue.882 token := yaml_token_t{883 typ: typ,884 start_mark: mark,885 end_mark: mark,886 }887 if number > -1 {888 number -= parser.tokens_parsed889 }890 yaml_insert_token(parser, number, &token)891 }892 return true893}894// Pop indentation levels from the indents stack until the current level895// becomes less or equal to the column. For each indentation level, append896// the BLOCK-END token.897func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool {898 // In the flow context, do nothing.899 if parser.flow_level > 0 {900 return true901 }902 // Loop through the indentation levels in the stack.903 for parser.indent > column {904 // Create a token and append it to the queue.905 token := yaml_token_t{906 typ: yaml_BLOCK_END_TOKEN,907 start_mark: parser.mark,908 end_mark: parser.mark,909 }910 yaml_insert_token(parser, -1, &token)911 // Pop the indentation level.912 parser.indent = parser.indents[len(parser.indents)-1]913 parser.indents = parser.indents[:len(parser.indents)-1]914 }915 return true916}917// Initialize the scanner and produce the STREAM-START token.918func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {919 // Set the initial indentation.920 parser.indent = -1921 // Initialize the simple key stack.922 parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})923 // A simple key is allowed at the beginning of the stream.924 parser.simple_key_allowed = true925 // We have started.926 parser.stream_start_produced = true927 // Create the STREAM-START token and append it to the queue.928 token := yaml_token_t{929 typ: yaml_STREAM_START_TOKEN,930 start_mark: parser.mark,931 end_mark: parser.mark,932 encoding: parser.encoding,933 }934 yaml_insert_token(parser, -1, &token)935 return true936}937// Produce the STREAM-END token and shut down the scanner.938func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {939 // Force new line.940 if parser.mark.column != 0 {941 parser.mark.column = 0942 parser.mark.line++943 }944 // Reset the indentation level.945 if !yaml_parser_unroll_indent(parser, -1) {946 return false947 }948 // Reset simple keys.949 if !yaml_parser_remove_simple_key(parser) {950 return false951 }952 parser.simple_key_allowed = false953 // Create the STREAM-END token and append it to the queue.954 token := yaml_token_t{955 typ: yaml_STREAM_END_TOKEN,956 start_mark: parser.mark,957 end_mark: parser.mark,958 }959 yaml_insert_token(parser, -1, &token)960 return true961}962// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.963func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {964 // Reset the indentation level.965 if !yaml_parser_unroll_indent(parser, -1) {966 return false967 }968 // Reset simple keys.969 if !yaml_parser_remove_simple_key(parser) {970 return false971 }972 parser.simple_key_allowed = false973 // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.974 token := yaml_token_t{}975 if !yaml_parser_scan_directive(parser, &token) {976 return false977 }978 // Append the token to the queue.979 yaml_insert_token(parser, -1, &token)980 return true981}982// Produce the DOCUMENT-START or DOCUMENT-END token.983func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {984 // Reset the indentation level.985 if !yaml_parser_unroll_indent(parser, -1) {986 return false987 }988 // Reset simple keys.989 if !yaml_parser_remove_simple_key(parser) {990 return false991 }992 parser.simple_key_allowed = false993 // Consume the token.994 start_mark := parser.mark995 skip(parser)996 skip(parser)997 skip(parser)998 end_mark := parser.mark999 // Create the DOCUMENT-START or DOCUMENT-END token.1000 token := yaml_token_t{1001 typ: typ,1002 start_mark: start_mark,1003 end_mark: end_mark,1004 }1005 // Append the token to the queue.1006 yaml_insert_token(parser, -1, &token)1007 return true1008}1009// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.1010func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {1011 // The indicators '[' and '{' may start a simple key.1012 if !yaml_parser_save_simple_key(parser) {1013 return false1014 }1015 // Increase the flow level.1016 if !yaml_parser_increase_flow_level(parser) {1017 return false1018 }1019 // A simple key may follow the indicators '[' and '{'.1020 parser.simple_key_allowed = true1021 // Consume the token.1022 start_mark := parser.mark1023 skip(parser)1024 end_mark := parser.mark1025 // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.1026 token := yaml_token_t{1027 typ: typ,1028 start_mark: start_mark,1029 end_mark: end_mark,1030 }1031 // Append the token to the queue.1032 yaml_insert_token(parser, -1, &token)1033 return true1034}1035// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.1036func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool {1037 // Reset any potential simple key on the current flow level.1038 if !yaml_parser_remove_simple_key(parser) {1039 return false1040 }1041 // Decrease the flow level.1042 if !yaml_parser_decrease_flow_level(parser) {1043 return false1044 }1045 // No simple keys after the indicators ']' and '}'.1046 parser.simple_key_allowed = false1047 // Consume the token.1048 start_mark := parser.mark1049 skip(parser)1050 end_mark := parser.mark1051 // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.1052 token := yaml_token_t{1053 typ: typ,1054 start_mark: start_mark,1055 end_mark: end_mark,1056 }1057 // Append the token to the queue.1058 yaml_insert_token(parser, -1, &token)1059 return true1060}1061// Produce the FLOW-ENTRY token.1062func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {1063 // Reset any potential simple keys on the current flow level.1064 if !yaml_parser_remove_simple_key(parser) {1065 return false1066 }1067 // Simple keys are allowed after ','.1068 parser.simple_key_allowed = true1069 // Consume the token.1070 start_mark := parser.mark1071 skip(parser)1072 end_mark := parser.mark1073 // Create the FLOW-ENTRY token and append it to the queue.1074 token := yaml_token_t{1075 typ: yaml_FLOW_ENTRY_TOKEN,1076 start_mark: start_mark,1077 end_mark: end_mark,1078 }1079 yaml_insert_token(parser, -1, &token)1080 return true1081}1082// Produce the BLOCK-ENTRY token.1083func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {1084 // Check if the scanner is in the block context.1085 if parser.flow_level == 0 {1086 // Check if we are allowed to start a new entry.1087 if !parser.simple_key_allowed {1088 return yaml_parser_set_scanner_error(parser, "", parser.mark,1089 "block sequence entries are not allowed in this context")1090 }1091 // Add the BLOCK-SEQUENCE-START token if needed.1092 if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) {1093 return false1094 }1095 } else {1096 // It is an error for the '-' indicator to occur in the flow context,1097 // but we let the Parser detect and report about it because the Parser1098 // is able to point to the context.1099 }1100 // Reset any potential simple keys on the current flow level.1101 if !yaml_parser_remove_simple_key(parser) {1102 return false1103 }1104 // Simple keys are allowed after '-'.1105 parser.simple_key_allowed = true1106 // Consume the token.1107 start_mark := parser.mark1108 skip(parser)1109 end_mark := parser.mark1110 // Create the BLOCK-ENTRY token and append it to the queue.1111 token := yaml_token_t{1112 typ: yaml_BLOCK_ENTRY_TOKEN,1113 start_mark: start_mark,1114 end_mark: end_mark,1115 }1116 yaml_insert_token(parser, -1, &token)1117 return true1118}1119// Produce the KEY token.1120func yaml_parser_fetch_key(parser *yaml_parser_t) bool {1121 // In the block context, additional checks are required.1122 if parser.flow_level == 0 {1123 // Check if we are allowed to start a new key (not nessesary simple).1124 if !parser.simple_key_allowed {1125 return yaml_parser_set_scanner_error(parser, "", parser.mark,1126 "mapping keys are not allowed in this context")1127 }1128 // Add the BLOCK-MAPPING-START token if needed.1129 if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {1130 return false1131 }1132 }1133 // Reset any potential simple keys on the current flow level.1134 if !yaml_parser_remove_simple_key(parser) {1135 return false1136 }1137 // Simple keys are allowed after '?' in the block context.1138 parser.simple_key_allowed = parser.flow_level == 01139 // Consume the token.1140 start_mark := parser.mark1141 skip(parser)1142 end_mark := parser.mark1143 // Create the KEY token and append it to the queue.1144 token := yaml_token_t{1145 typ: yaml_KEY_TOKEN,1146 start_mark: start_mark,1147 end_mark: end_mark,1148 }1149 yaml_insert_token(parser, -1, &token)1150 return true1151}1152// Produce the VALUE token.1153func yaml_parser_fetch_value(parser *yaml_parser_t) bool {1154 simple_key := &parser.simple_keys[len(parser.simple_keys)-1]1155 // Have we found a simple key?1156 if simple_key.possible {1157 // Create the KEY token and insert it into the queue.1158 token := yaml_token_t{1159 typ: yaml_KEY_TOKEN,1160 start_mark: simple_key.mark,1161 end_mark: simple_key.mark,1162 }1163 yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token)1164 // In the block context, we may need to add the BLOCK-MAPPING-START token.1165 if !yaml_parser_roll_indent(parser, simple_key.mark.column,1166 simple_key.token_number,1167 yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) {1168 return false1169 }1170 // Remove the simple key.1171 simple_key.possible = false1172 // A simple key cannot follow another simple key.1173 parser.simple_key_allowed = false1174 } else {1175 // The ':' indicator follows a complex key.1176 // In the block context, extra checks are required.1177 if parser.flow_level == 0 {1178 // Check if we are allowed to start a complex value.1179 if !parser.simple_key_allowed {1180 return yaml_parser_set_scanner_error(parser, "", parser.mark,1181 "mapping values are not allowed in this context")1182 }1183 // Add the BLOCK-MAPPING-START token if needed.1184 if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {1185 return false1186 }1187 }1188 // Simple keys after ':' are allowed in the block context.1189 parser.simple_key_allowed = parser.flow_level == 01190 }1191 // Consume the token.1192 start_mark := parser.mark1193 skip(parser)1194 end_mark := parser.mark1195 // Create the VALUE token and append it to the queue.1196 token := yaml_token_t{1197 typ: yaml_VALUE_TOKEN,1198 start_mark: start_mark,1199 end_mark: end_mark,1200 }1201 yaml_insert_token(parser, -1, &token)1202 return true1203}1204// Produce the ALIAS or ANCHOR token.1205func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool {1206 // An anchor or an alias could be a simple key.1207 if !yaml_parser_save_simple_key(parser) {1208 return false1209 }1210 // A simple key cannot follow an anchor or an alias.1211 parser.simple_key_allowed = false1212 // Create the ALIAS or ANCHOR token and append it to the queue.1213 var token yaml_token_t1214 if !yaml_parser_scan_anchor(parser, &token, typ) {1215 return false1216 }1217 yaml_insert_token(parser, -1, &token)1218 return true1219}1220// Produce the TAG token.1221func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {1222 // A tag could be a simple key.1223 if !yaml_parser_save_simple_key(parser) {1224 return false1225 }1226 // A simple key cannot follow a tag.1227 parser.simple_key_allowed = false1228 // Create the TAG token and append it to the queue.1229 var token yaml_token_t1230 if !yaml_parser_scan_tag(parser, &token) {1231 return false1232 }1233 yaml_insert_token(parser, -1, &token)1234 return true1235}1236// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.1237func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool {1238 // Remove any potential simple keys.1239 if !yaml_parser_remove_simple_key(parser) {1240 return false1241 }1242 // A simple key may follow a block scalar.1243 parser.simple_key_allowed = true1244 // Create the SCALAR token and append it to the queue.1245 var token yaml_token_t1246 if !yaml_parser_scan_block_scalar(parser, &token, literal) {1247 return false1248 }1249 yaml_insert_token(parser, -1, &token)1250 return true1251}1252// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.1253func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool {1254 // A plain scalar could be a simple key.1255 if !yaml_parser_save_simple_key(parser) {1256 return false1257 }1258 // A simple key cannot follow a flow scalar.1259 parser.simple_key_allowed = false1260 // Create the SCALAR token and append it to the queue.1261 var token yaml_token_t1262 if !yaml_parser_scan_flow_scalar(parser, &token, single) {1263 return false1264 }1265 yaml_insert_token(parser, -1, &token)1266 return true1267}1268// Produce the SCALAR(...,plain) token.1269func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {1270 // A plain scalar could be a simple key.1271 if !yaml_parser_save_simple_key(parser) {1272 return false1273 }1274 // A simple key cannot follow a flow scalar.1275 parser.simple_key_allowed = false1276 // Create the SCALAR token and append it to the queue.1277 var token yaml_token_t1278 if !yaml_parser_scan_plain_scalar(parser, &token) {1279 return false1280 }1281 yaml_insert_token(parser, -1, &token)1282 return true1283}1284// Eat whitespaces and comments until the next token is found.1285func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {1286 // Until the next token is not found.1287 for {1288 // Allow the BOM mark to start a line.1289 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1290 return false1291 }1292 if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) {1293 skip(parser)1294 }1295 // Eat whitespaces.1296 // Tabs are allowed:1297 // - in the flow context1298 // - in the block context, but not at the beginning of the line or1299 // after '-', '?', or ':' (complex value).1300 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1301 return false1302 }1303 for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {1304 skip(parser)1305 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1306 return false1307 }1308 }1309 // Eat a comment until a line break.1310 if parser.buffer[parser.buffer_pos] == '#' {1311 for !is_breakz(parser.buffer, parser.buffer_pos) {1312 skip(parser)1313 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1314 return false1315 }1316 }1317 }1318 // If it is a line break, eat it.1319 if is_break(parser.buffer, parser.buffer_pos) {1320 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {1321 return false1322 }1323 skip_line(parser)1324 // In the block context, a new line may start a simple key.1325 if parser.flow_level == 0 {1326 parser.simple_key_allowed = true1327 }1328 } else {1329 break // We have found a token.1330 }1331 }1332 return true1333}1334// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.1335//1336// Scope:1337// %YAML 1.1 # a comment \n1338// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^1339// %TAG !yaml! tag:yaml.org,2002: \n1340// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^1341//1342func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {1343 // Eat '%'.1344 start_mark := parser.mark1345 skip(parser)1346 // Scan the directive name.1347 var name []byte1348 if !yaml_parser_scan_directive_name(parser, start_mark, &name) {1349 return false1350 }1351 // Is it a YAML directive?1352 if bytes.Equal(name, []byte("YAML")) {1353 // Scan the VERSION directive value.1354 var major, minor int81355 if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) {1356 return false1357 }1358 end_mark := parser.mark1359 // Create a VERSION-DIRECTIVE token.1360 *token = yaml_token_t{1361 typ: yaml_VERSION_DIRECTIVE_TOKEN,1362 start_mark: start_mark,1363 end_mark: end_mark,1364 major: major,1365 minor: minor,1366 }1367 // Is it a TAG directive?1368 } else if bytes.Equal(name, []byte("TAG")) {1369 // Scan the TAG directive value.1370 var handle, prefix []byte1371 if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) {1372 return false1373 }1374 end_mark := parser.mark1375 // Create a TAG-DIRECTIVE token.1376 *token = yaml_token_t{1377 typ: yaml_TAG_DIRECTIVE_TOKEN,1378 start_mark: start_mark,1379 end_mark: end_mark,1380 value: handle,1381 prefix: prefix,1382 }1383 // Unknown directive.1384 } else {1385 yaml_parser_set_scanner_error(parser, "while scanning a directive",1386 start_mark, "found unknown directive name")1387 return false1388 }1389 // Eat the rest of the line including any comments.1390 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1391 return false1392 }1393 for is_blank(parser.buffer, parser.buffer_pos) {1394 skip(parser)1395 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1396 return false1397 }1398 }1399 if parser.buffer[parser.buffer_pos] == '#' {1400 for !is_breakz(parser.buffer, parser.buffer_pos) {1401 skip(parser)1402 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1403 return false1404 }1405 }1406 }1407 // Check if we are at the end of the line.1408 if !is_breakz(parser.buffer, parser.buffer_pos) {1409 yaml_parser_set_scanner_error(parser, "while scanning a directive",1410 start_mark, "did not find expected comment or line break")1411 return false1412 }1413 // Eat a line break.1414 if is_break(parser.buffer, parser.buffer_pos) {1415 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {1416 return false1417 }1418 skip_line(parser)1419 }1420 return true1421}1422// Scan the directive name.1423//1424// Scope:1425// %YAML 1.1 # a comment \n1426// ^^^^1427// %TAG !yaml! tag:yaml.org,2002: \n1428// ^^^1429//1430func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {1431 // Consume the directive name.1432 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1433 return false1434 }1435 var s []byte1436 for is_alpha(parser.buffer, parser.buffer_pos) {1437 s = read(parser, s)1438 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1439 return false1440 }1441 }1442 // Check if the name is empty.1443 if len(s) == 0 {1444 yaml_parser_set_scanner_error(parser, "while scanning a directive",1445 start_mark, "could not find expected directive name")1446 return false1447 }1448 // Check for an blank character after the name.1449 if !is_blankz(parser.buffer, parser.buffer_pos) {1450 yaml_parser_set_scanner_error(parser, "while scanning a directive",1451 start_mark, "found unexpected non-alphabetical character")1452 return false1453 }1454 *name = s1455 return true1456}1457// Scan the value of VERSION-DIRECTIVE.1458//1459// Scope:1460// %YAML 1.1 # a comment \n1461// ^^^^^^1462func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {1463 // Eat whitespaces.1464 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1465 return false1466 }1467 for is_blank(parser.buffer, parser.buffer_pos) {1468 skip(parser)1469 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1470 return false1471 }1472 }1473 // Consume the major version number.1474 if !yaml_parser_scan_version_directive_number(parser, start_mark, major) {1475 return false1476 }1477 // Eat '.'.1478 if parser.buffer[parser.buffer_pos] != '.' {1479 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",1480 start_mark, "did not find expected digit or '.' character")1481 }1482 skip(parser)1483 // Consume the minor version number.1484 if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) {1485 return false1486 }1487 return true1488}1489const max_number_length = 21490// Scan the version number of VERSION-DIRECTIVE.1491//1492// Scope:1493// %YAML 1.1 # a comment \n1494// ^1495// %YAML 1.1 # a comment \n1496// ^1497func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {1498 // Repeat while the next character is digit.1499 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1500 return false1501 }1502 var value, length int81503 for is_digit(parser.buffer, parser.buffer_pos) {1504 // Check if the number is too long.1505 length++1506 if length > max_number_length {1507 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",1508 start_mark, "found extremely long version number")1509 }1510 value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos))1511 skip(parser)1512 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1513 return false1514 }1515 }1516 // Check if the number was present.1517 if length == 0 {1518 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",1519 start_mark, "did not find expected version number")1520 }1521 *number = value1522 return true1523}1524// Scan the value of a TAG-DIRECTIVE token.1525//1526// Scope:1527// %TAG !yaml! tag:yaml.org,2002: \n1528// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^1529//1530func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {1531 var handle_value, prefix_value []byte1532 // Eat whitespaces.1533 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1534 return false1535 }1536 for is_blank(parser.buffer, parser.buffer_pos) {1537 skip(parser)1538 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1539 return false1540 }1541 }1542 // Scan a handle.1543 if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) {1544 return false1545 }1546 // Expect a whitespace.1547 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1548 return false1549 }1550 if !is_blank(parser.buffer, parser.buffer_pos) {1551 yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",1552 start_mark, "did not find expected whitespace")1553 return false1554 }1555 // Eat whitespaces.1556 for is_blank(parser.buffer, parser.buffer_pos) {1557 skip(parser)1558 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1559 return false1560 }1561 }1562 // Scan a prefix.1563 if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) {1564 return false1565 }1566 // Expect a whitespace or line break.1567 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1568 return false1569 }1570 if !is_blankz(parser.buffer, parser.buffer_pos) {1571 yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",1572 start_mark, "did not find expected whitespace or line break")1573 return false1574 }1575 *handle = handle_value1576 *prefix = prefix_value1577 return true1578}1579func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool {1580 var s []byte1581 // Eat the indicator character.1582 start_mark := parser.mark1583 skip(parser)1584 // Consume the value.1585 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1586 return false1587 }1588 for is_alpha(parser.buffer, parser.buffer_pos) {1589 s = read(parser, s)1590 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1591 return false1592 }1593 }1594 end_mark := parser.mark1595 /*1596 * Check if length of the anchor is greater than 0 and it is followed by1597 * a whitespace character or one of the indicators:1598 *1599 * '?', ':', ',', ']', '}', '%', '@', '`'.1600 */1601 if len(s) == 0 ||1602 !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||1603 parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||1604 parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||1605 parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||1606 parser.buffer[parser.buffer_pos] == '`') {1607 context := "while scanning an alias"1608 if typ == yaml_ANCHOR_TOKEN {1609 context = "while scanning an anchor"1610 }1611 yaml_parser_set_scanner_error(parser, context, start_mark,1612 "did not find expected alphabetic or numeric character")1613 return false1614 }1615 // Create a token.1616 *token = yaml_token_t{1617 typ: typ,1618 start_mark: start_mark,1619 end_mark: end_mark,1620 value: s,1621 }1622 return true1623}1624/*1625 * Scan a TAG token.1626 */1627func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool {1628 var handle, suffix []byte1629 start_mark := parser.mark1630 // Check if the tag is in the canonical form.1631 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {1632 return false1633 }1634 if parser.buffer[parser.buffer_pos+1] == '<' {1635 // Keep the handle as ''1636 // Eat '!<'1637 skip(parser)1638 skip(parser)1639 // Consume the tag value.1640 if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {1641 return false1642 }1643 // Check for '>' and eat it.1644 if parser.buffer[parser.buffer_pos] != '>' {1645 yaml_parser_set_scanner_error(parser, "while scanning a tag",1646 start_mark, "did not find the expected '>'")1647 return false1648 }1649 skip(parser)1650 } else {1651 // The tag has either the '!suffix' or the '!handle!suffix' form.1652 // First, try to scan a handle.1653 if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) {1654 return false1655 }1656 // Check if it is, indeed, handle.1657 if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {1658 // Scan the suffix now.1659 if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {1660 return false1661 }1662 } else {1663 // It wasn't a handle after all. Scan the rest of the tag.1664 if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) {1665 return false1666 }1667 // Set the handle to '!'.1668 handle = []byte{'!'}1669 // A special case: the '!' tag. Set the handle to '' and the1670 // suffix to '!'.1671 if len(suffix) == 0 {1672 handle, suffix = suffix, handle1673 }1674 }1675 }1676 // Check the character which ends the tag.1677 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1678 return false1679 }1680 if !is_blankz(parser.buffer, parser.buffer_pos) {1681 yaml_parser_set_scanner_error(parser, "while scanning a tag",1682 start_mark, "did not find expected whitespace or line break")1683 return false1684 }1685 end_mark := parser.mark1686 // Create a token.1687 *token = yaml_token_t{1688 typ: yaml_TAG_TOKEN,1689 start_mark: start_mark,1690 end_mark: end_mark,1691 value: handle,1692 suffix: suffix,1693 }1694 return true1695}1696// Scan a tag handle.1697func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool {1698 // Check the initial '!' character.1699 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1700 return false1701 }1702 if parser.buffer[parser.buffer_pos] != '!' {1703 yaml_parser_set_scanner_tag_error(parser, directive,1704 start_mark, "did not find expected '!'")1705 return false1706 }1707 var s []byte1708 // Copy the '!' character.1709 s = read(parser, s)1710 // Copy all subsequent alphabetical and numerical characters.1711 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1712 return false1713 }1714 for is_alpha(parser.buffer, parser.buffer_pos) {1715 s = read(parser, s)1716 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1717 return false1718 }1719 }1720 // Check if the trailing character is '!' and copy it.1721 if parser.buffer[parser.buffer_pos] == '!' {1722 s = read(parser, s)1723 } else {1724 // It's either the '!' tag or not really a tag handle. If it's a %TAG1725 // directive, it's an error. If it's a tag token, it must be a part of URI.1726 if directive && string(s) != "!" {1727 yaml_parser_set_scanner_tag_error(parser, directive,1728 start_mark, "did not find expected '!'")1729 return false1730 }1731 }1732 *handle = s1733 return true1734}1735// Scan a tag.1736func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {1737 //size_t length = head ? strlen((char *)head) : 01738 var s []byte1739 hasTag := len(head) > 01740 // Copy the head if needed.1741 //1742 // Note that we don't copy the leading '!' character.1743 if len(head) > 1 {1744 s = append(s, head[1:]...)1745 }1746 // Scan the tag.1747 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1748 return false1749 }1750 // The set of characters that may appear in URI is as follows:1751 //1752 // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',1753 // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',1754 // '%'.1755 // [Go] Convert this into more reasonable logic.1756 for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||1757 parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||1758 parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||1759 parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' ||1760 parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' ||1761 parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' ||1762 parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' ||1763 parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' ||1764 parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' ||1765 parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' ||1766 parser.buffer[parser.buffer_pos] == '%' {1767 // Check if it is a URI-escape sequence.1768 if parser.buffer[parser.buffer_pos] == '%' {1769 if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) {1770 return false1771 }1772 } else {1773 s = read(parser, s)1774 }1775 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1776 return false1777 }1778 hasTag = true1779 }1780 if !hasTag {1781 yaml_parser_set_scanner_tag_error(parser, directive,1782 start_mark, "did not find expected tag URI")1783 return false1784 }1785 *uri = s1786 return true1787}1788// Decode an URI-escape sequence corresponding to a single UTF-8 character.1789func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool {1790 // Decode the required number of characters.1791 w := 10241792 for w > 0 {1793 // Check for a URI-escaped octet.1794 if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {1795 return false1796 }1797 if !(parser.buffer[parser.buffer_pos] == '%' &&1798 is_hex(parser.buffer, parser.buffer_pos+1) &&1799 is_hex(parser.buffer, parser.buffer_pos+2)) {1800 return yaml_parser_set_scanner_tag_error(parser, directive,1801 start_mark, "did not find URI escaped octet")1802 }1803 // Get the octet.1804 octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2))1805 // If it is the leading octet, determine the length of the UTF-8 sequence.1806 if w == 1024 {1807 w = width(octet)1808 if w == 0 {1809 return yaml_parser_set_scanner_tag_error(parser, directive,1810 start_mark, "found an incorrect leading UTF-8 octet")1811 }1812 } else {1813 // Check if the trailing octet is correct.1814 if octet&0xC0 != 0x80 {1815 return yaml_parser_set_scanner_tag_error(parser, directive,1816 start_mark, "found an incorrect trailing UTF-8 octet")1817 }1818 }1819 // Copy the octet and move the pointers.1820 *s = append(*s, octet)1821 skip(parser)1822 skip(parser)1823 skip(parser)1824 w--1825 }1826 return true1827}1828// Scan a block scalar.1829func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool {1830 // Eat the indicator '|' or '>'.1831 start_mark := parser.mark1832 skip(parser)1833 // Scan the additional block scalar indicators.1834 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1835 return false1836 }1837 // Check for a chomping indicator.1838 var chomping, increment int1839 if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {1840 // Set the chomping method and eat the indicator.1841 if parser.buffer[parser.buffer_pos] == '+' {1842 chomping = +11843 } else {1844 chomping = -11845 }1846 skip(parser)1847 // Check for an indentation indicator.1848 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1849 return false1850 }1851 if is_digit(parser.buffer, parser.buffer_pos) {1852 // Check that the indentation is greater than 0.1853 if parser.buffer[parser.buffer_pos] == '0' {1854 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",1855 start_mark, "found an indentation indicator equal to 0")1856 return false1857 }1858 // Get the indentation level and eat the indicator.1859 increment = as_digit(parser.buffer, parser.buffer_pos)1860 skip(parser)1861 }1862 } else if is_digit(parser.buffer, parser.buffer_pos) {1863 // Do the same as above, but in the opposite order.1864 if parser.buffer[parser.buffer_pos] == '0' {1865 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",1866 start_mark, "found an indentation indicator equal to 0")1867 return false1868 }1869 increment = as_digit(parser.buffer, parser.buffer_pos)1870 skip(parser)1871 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1872 return false1873 }1874 if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {1875 if parser.buffer[parser.buffer_pos] == '+' {1876 chomping = +11877 } else {1878 chomping = -11879 }1880 skip(parser)1881 }1882 }1883 // Eat whitespaces and comments to the end of the line.1884 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1885 return false1886 }1887 for is_blank(parser.buffer, parser.buffer_pos) {1888 skip(parser)1889 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1890 return false1891 }1892 }1893 if parser.buffer[parser.buffer_pos] == '#' {1894 for !is_breakz(parser.buffer, parser.buffer_pos) {1895 skip(parser)1896 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1897 return false1898 }1899 }1900 }1901 // Check if we are at the end of the line.1902 if !is_breakz(parser.buffer, parser.buffer_pos) {1903 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",1904 start_mark, "did not find expected comment or line break")1905 return false1906 }1907 // Eat a line break.1908 if is_break(parser.buffer, parser.buffer_pos) {1909 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {1910 return false1911 }1912 skip_line(parser)1913 }1914 end_mark := parser.mark1915 // Set the indentation level if it was specified.1916 var indent int1917 if increment > 0 {1918 if parser.indent >= 0 {1919 indent = parser.indent + increment1920 } else {1921 indent = increment1922 }1923 }1924 // Scan the leading line breaks and determine the indentation level if needed.1925 var s, leading_break, trailing_breaks []byte1926 if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {1927 return false1928 }1929 // Scan the block scalar content.1930 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1931 return false1932 }1933 var leading_blank, trailing_blank bool1934 for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) {1935 // We are at the beginning of a non-empty line.1936 // Is it a trailing whitespace?1937 trailing_blank = is_blank(parser.buffer, parser.buffer_pos)1938 // Check if we need to fold the leading line break.1939 if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {1940 // Do we need to join the lines by space?1941 if len(trailing_breaks) == 0 {1942 s = append(s, ' ')1943 }1944 } else {1945 s = append(s, leading_break...)1946 }1947 leading_break = leading_break[:0]1948 // Append the remaining line breaks.1949 s = append(s, trailing_breaks...)1950 trailing_breaks = trailing_breaks[:0]1951 // Is it a leading whitespace?1952 leading_blank = is_blank(parser.buffer, parser.buffer_pos)1953 // Consume the current line.1954 for !is_breakz(parser.buffer, parser.buffer_pos) {1955 s = read(parser, s)1956 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1957 return false1958 }1959 }1960 // Consume the line break.1961 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {1962 return false1963 }1964 leading_break = read_line(parser, leading_break)1965 // Eat the following indentation spaces and line breaks.1966 if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {1967 return false1968 }1969 }1970 // Chomp the tail.1971 if chomping != -1 {1972 s = append(s, leading_break...)1973 }1974 if chomping == 1 {1975 s = append(s, trailing_breaks...)1976 }1977 // Create a token.1978 *token = yaml_token_t{1979 typ: yaml_SCALAR_TOKEN,1980 start_mark: start_mark,1981 end_mark: end_mark,1982 value: s,1983 style: yaml_LITERAL_SCALAR_STYLE,1984 }1985 if !literal {1986 token.style = yaml_FOLDED_SCALAR_STYLE1987 }1988 return true1989}1990// Scan indentation spaces and line breaks for a block scalar. Determine the1991// indentation level if needed.1992func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool {1993 *end_mark = parser.mark1994 // Eat the indentation spaces and line breaks.1995 max_indent := 01996 for {1997 // Eat the indentation spaces.1998 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {1999 return false2000 }2001 for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) {2002 skip(parser)2003 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {2004 return false2005 }2006 }2007 if parser.mark.column > max_indent {2008 max_indent = parser.mark.column2009 }2010 // Check for a tab character messing the indentation.2011 if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) {2012 return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",2013 start_mark, "found a tab character where an indentation space is expected")2014 }2015 // Have we found a non-empty line?2016 if !is_break(parser.buffer, parser.buffer_pos) {2017 break2018 }2019 // Consume the line break.2020 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {2021 return false2022 }2023 // [Go] Should really be returning breaks instead.2024 *breaks = read_line(parser, *breaks)2025 *end_mark = parser.mark2026 }2027 // Determine the indentation level if needed.2028 if *indent == 0 {2029 *indent = max_indent2030 if *indent < parser.indent+1 {2031 *indent = parser.indent + 12032 }2033 if *indent < 1 {2034 *indent = 12035 }2036 }2037 return true2038}2039// Scan a quoted scalar.2040func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool {2041 // Eat the left quote.2042 start_mark := parser.mark2043 skip(parser)2044 // Consume the content of the quoted scalar.2045 var s, leading_break, trailing_breaks, whitespaces []byte2046 for {2047 // Check that there are no document indicators at the beginning of the line.2048 if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {2049 return false2050 }2051 if parser.mark.column == 0 &&2052 ((parser.buffer[parser.buffer_pos+0] == '-' &&2053 parser.buffer[parser.buffer_pos+1] == '-' &&2054 parser.buffer[parser.buffer_pos+2] == '-') ||2055 (parser.buffer[parser.buffer_pos+0] == '.' &&2056 parser.buffer[parser.buffer_pos+1] == '.' &&2057 parser.buffer[parser.buffer_pos+2] == '.')) &&2058 is_blankz(parser.buffer, parser.buffer_pos+3) {2059 yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",2060 start_mark, "found unexpected document indicator")2061 return false2062 }2063 // Check for EOF.2064 if is_z(parser.buffer, parser.buffer_pos) {2065 yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",2066 start_mark, "found unexpected end of stream")2067 return false2068 }2069 // Consume non-blank characters.2070 leading_blanks := false2071 for !is_blankz(parser.buffer, parser.buffer_pos) {2072 if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {2073 // Is is an escaped single quote.2074 s = append(s, '\'')2075 skip(parser)2076 skip(parser)2077 } else if single && parser.buffer[parser.buffer_pos] == '\'' {2078 // It is a right single quote.2079 break2080 } else if !single && parser.buffer[parser.buffer_pos] == '"' {2081 // It is a right double quote.2082 break2083 } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) {2084 // It is an escaped line break.2085 if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {2086 return false2087 }2088 skip(parser)2089 skip_line(parser)2090 leading_blanks = true2091 break2092 } else if !single && parser.buffer[parser.buffer_pos] == '\\' {2093 // It is an escape sequence.2094 code_length := 02095 // Check the escape character.2096 switch parser.buffer[parser.buffer_pos+1] {2097 case '0':2098 s = append(s, 0)2099 case 'a':2100 s = append(s, '\x07')2101 case 'b':2102 s = append(s, '\x08')2103 case 't', '\t':2104 s = append(s, '\x09')2105 case 'n':2106 s = append(s, '\x0A')2107 case 'v':2108 s = append(s, '\x0B')2109 case 'f':2110 s = append(s, '\x0C')2111 case 'r':2112 s = append(s, '\x0D')2113 case 'e':2114 s = append(s, '\x1B')2115 case ' ':2116 s = append(s, '\x20')2117 case '"':2118 s = append(s, '"')2119 case '\'':2120 s = append(s, '\'')2121 case '\\':2122 s = append(s, '\\')2123 case 'N': // NEL (#x85)2124 s = append(s, '\xC2')2125 s = append(s, '\x85')2126 case '_': // #xA02127 s = append(s, '\xC2')2128 s = append(s, '\xA0')2129 case 'L': // LS (#x2028)2130 s = append(s, '\xE2')2131 s = append(s, '\x80')2132 s = append(s, '\xA8')2133 case 'P': // PS (#x2029)2134 s = append(s, '\xE2')2135 s = append(s, '\x80')2136 s = append(s, '\xA9')2137 case 'x':2138 code_length = 22139 case 'u':2140 code_length = 42141 case 'U':2142 code_length = 82143 default:2144 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",2145 start_mark, "found unknown escape character")2146 return false2147 }2148 skip(parser)2149 skip(parser)2150 // Consume an arbitrary escape code.2151 if code_length > 0 {2152 var value int2153 // Scan the character value.2154 if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) {2155 return false2156 }2157 for k := 0; k < code_length; k++ {2158 if !is_hex(parser.buffer, parser.buffer_pos+k) {2159 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",2160 start_mark, "did not find expected hexdecimal number")2161 return false2162 }2163 value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k)2164 }2165 // Check the value and write the character.2166 if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {2167 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",2168 start_mark, "found invalid Unicode character escape code")2169 return false2170 }2171 if value <= 0x7F {2172 s = append(s, byte(value))2173 } else if value <= 0x7FF {2174 s = append(s, byte(0xC0+(value>>6)))2175 s = append(s, byte(0x80+(value&0x3F)))2176 } else if value <= 0xFFFF {2177 s = append(s, byte(0xE0+(value>>12)))2178 s = append(s, byte(0x80+((value>>6)&0x3F)))2179 s = append(s, byte(0x80+(value&0x3F)))2180 } else {2181 s = append(s, byte(0xF0+(value>>18)))2182 s = append(s, byte(0x80+((value>>12)&0x3F)))2183 s = append(s, byte(0x80+((value>>6)&0x3F)))2184 s = append(s, byte(0x80+(value&0x3F)))2185 }2186 // Advance the pointer.2187 for k := 0; k < code_length; k++ {2188 skip(parser)2189 }2190 }2191 } else {2192 // It is a non-escaped non-blank character.2193 s = read(parser, s)2194 }2195 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {2196 return false2197 }2198 }2199 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {2200 return false2201 }2202 // Check if we are at the end of the scalar.2203 if single {2204 if parser.buffer[parser.buffer_pos] == '\'' {2205 break2206 }2207 } else {2208 if parser.buffer[parser.buffer_pos] == '"' {2209 break2210 }2211 }2212 // Consume blank characters.2213 for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {2214 if is_blank(parser.buffer, parser.buffer_pos) {2215 // Consume a space or a tab character.2216 if !leading_blanks {2217 whitespaces = read(parser, whitespaces)2218 } else {2219 skip(parser)2220 }2221 } else {2222 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {2223 return false2224 }2225 // Check if it is a first line break.2226 if !leading_blanks {2227 whitespaces = whitespaces[:0]2228 leading_break = read_line(parser, leading_break)2229 leading_blanks = true2230 } else {2231 trailing_breaks = read_line(parser, trailing_breaks)2232 }2233 }2234 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {2235 return false2236 }2237 }2238 // Join the whitespaces or fold line breaks.2239 if leading_blanks {2240 // Do we need to fold line breaks?2241 if len(leading_break) > 0 && leading_break[0] == '\n' {2242 if len(trailing_breaks) == 0 {2243 s = append(s, ' ')2244 } else {2245 s = append(s, trailing_breaks...)2246 }2247 } else {2248 s = append(s, leading_break...)2249 s = append(s, trailing_breaks...)2250 }2251 trailing_breaks = trailing_breaks[:0]2252 leading_break = leading_break[:0]2253 } else {2254 s = append(s, whitespaces...)2255 whitespaces = whitespaces[:0]2256 }2257 }2258 // Eat the right quote.2259 skip(parser)2260 end_mark := parser.mark2261 // Create a token.2262 *token = yaml_token_t{2263 typ: yaml_SCALAR_TOKEN,2264 start_mark: start_mark,2265 end_mark: end_mark,2266 value: s,2267 style: yaml_SINGLE_QUOTED_SCALAR_STYLE,2268 }2269 if !single {2270 token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE2271 }2272 return true2273}2274// Scan a plain scalar.2275func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool {2276 var s, leading_break, trailing_breaks, whitespaces []byte2277 var leading_blanks bool2278 var indent = parser.indent + 12279 start_mark := parser.mark2280 end_mark := parser.mark2281 // Consume the content of the plain scalar.2282 for {2283 // Check for a document indicator.2284 if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {2285 return false2286 }2287 if parser.mark.column == 0 &&2288 ((parser.buffer[parser.buffer_pos+0] == '-' &&2289 parser.buffer[parser.buffer_pos+1] == '-' &&2290 parser.buffer[parser.buffer_pos+2] == '-') ||2291 (parser.buffer[parser.buffer_pos+0] == '.' &&2292 parser.buffer[parser.buffer_pos+1] == '.' &&2293 parser.buffer[parser.buffer_pos+2] == '.')) &&2294 is_blankz(parser.buffer, parser.buffer_pos+3) {2295 break2296 }2297 // Check for a comment.2298 if parser.buffer[parser.buffer_pos] == '#' {2299 break2300 }2301 // Consume non-blank characters.2302 for !is_blankz(parser.buffer, parser.buffer_pos) {2303 // Check for indicators that may end a plain scalar.2304 if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||2305 (parser.flow_level > 0 &&2306 (parser.buffer[parser.buffer_pos] == ',' ||2307 parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||2308 parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||2309 parser.buffer[parser.buffer_pos] == '}')) {2310 break2311 }2312 // Check if we need to join whitespaces and breaks.2313 if leading_blanks || len(whitespaces) > 0 {2314 if leading_blanks {2315 // Do we need to fold line breaks?2316 if leading_break[0] == '\n' {2317 if len(trailing_breaks) == 0 {2318 s = append(s, ' ')2319 } else {2320 s = append(s, trailing_breaks...)2321 }2322 } else {2323 s = append(s, leading_break...)2324 s = append(s, trailing_breaks...)2325 }2326 trailing_breaks = trailing_breaks[:0]2327 leading_break = leading_break[:0]2328 leading_blanks = false2329 } else {2330 s = append(s, whitespaces...)2331 whitespaces = whitespaces[:0]2332 }2333 }2334 // Copy the character.2335 s = read(parser, s)2336 end_mark = parser.mark2337 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {2338 return false2339 }2340 }2341 // Is it the end?2342 if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) {2343 break2344 }2345 // Consume blank characters.2346 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {2347 return false2348 }2349 for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {2350 if is_blank(parser.buffer, parser.buffer_pos) {2351 // Check for tab characters that abuse indentation.2352 if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {2353 yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",2354 start_mark, "found a tab character that violates indentation")2355 return false2356 }2357 // Consume a space or a tab character.2358 if !leading_blanks {2359 whitespaces = read(parser, whitespaces)2360 } else {2361 skip(parser)2362 }2363 } else {2364 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {2365 return false2366 }2367 // Check if it is a first line break.2368 if !leading_blanks {2369 whitespaces = whitespaces[:0]2370 leading_break = read_line(parser, leading_break)2371 leading_blanks = true2372 } else {2373 trailing_breaks = read_line(parser, trailing_breaks)2374 }2375 }2376 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {2377 return false2378 }2379 }2380 // Check indentation level.2381 if parser.flow_level == 0 && parser.mark.column < indent {2382 break2383 }2384 }2385 // Create a token.2386 *token = yaml_token_t{2387 typ: yaml_SCALAR_TOKEN,2388 start_mark: start_mark,2389 end_mark: end_mark,2390 value: s,2391 style: yaml_PLAIN_SCALAR_STYLE,2392 }2393 // Note that we change the 'simple_key_allowed' flag.2394 if leading_blanks {2395 parser.simple_key_allowed = true2396 }2397 return true2398}...
parserc.go
Source:parserc.go
1package yaml2import (3 "bytes"4)5// The parser implements the following grammar:6//7// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END8// implicit_document ::= block_node DOCUMENT-END*9// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*10// block_node_or_indentless_sequence ::=11// ALIAS12// | properties (block_content | indentless_block_sequence)?13// | block_content14// | indentless_block_sequence15// block_node ::= ALIAS16// | properties block_content?17// | block_content18// flow_node ::= ALIAS19// | properties flow_content?20// | flow_content21// properties ::= TAG ANCHOR? | ANCHOR TAG?22// block_content ::= block_collection | flow_collection | SCALAR23// flow_content ::= flow_collection | SCALAR24// block_collection ::= block_sequence | block_mapping25// flow_collection ::= flow_sequence | flow_mapping26// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END27// indentless_sequence ::= (BLOCK-ENTRY block_node?)+28// block_mapping ::= BLOCK-MAPPING_START29// ((KEY block_node_or_indentless_sequence?)?30// (VALUE block_node_or_indentless_sequence?)?)*31// BLOCK-END32// flow_sequence ::= FLOW-SEQUENCE-START33// (flow_sequence_entry FLOW-ENTRY)*34// flow_sequence_entry?35// FLOW-SEQUENCE-END36// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?37// flow_mapping ::= FLOW-MAPPING-START38// (flow_mapping_entry FLOW-ENTRY)*39// flow_mapping_entry?40// FLOW-MAPPING-END41// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?42// Peek the next token in the token queue.43func peek_token(parser *yaml_parser_t) *yaml_token_t {44 if parser.token_available || yaml_parser_fetch_more_tokens(parser) {45 return &parser.tokens[parser.tokens_head]46 }47 return nil48}49// Remove the next token from the queue (must be called after peek_token).50func skip_token(parser *yaml_parser_t) {51 parser.token_available = false52 parser.tokens_parsed++53 parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN54 parser.tokens_head++55}56// Get the next event.57func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {58 // Erase the event object.59 *event = yaml_event_t{}60 // No events after the end of the stream or error.61 if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE {62 return true63 }64 // Generate the next event.65 return yaml_parser_state_machine(parser, event)66}67// Set parser error.68func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool {69 parser.error = yaml_PARSER_ERROR70 parser.problem = problem71 parser.problem_mark = problem_mark72 return false73}74func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool {75 parser.error = yaml_PARSER_ERROR76 parser.context = context77 parser.context_mark = context_mark78 parser.problem = problem79 parser.problem_mark = problem_mark80 return false81}82// State dispatcher.83func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool {84 //trace("yaml_parser_state_machine", "state:", parser.state.String())85 switch parser.state {86 case yaml_PARSE_STREAM_START_STATE:87 return yaml_parser_parse_stream_start(parser, event)88 case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:89 return yaml_parser_parse_document_start(parser, event, true)90 case yaml_PARSE_DOCUMENT_START_STATE:91 return yaml_parser_parse_document_start(parser, event, false)92 case yaml_PARSE_DOCUMENT_CONTENT_STATE:93 return yaml_parser_parse_document_content(parser, event)94 case yaml_PARSE_DOCUMENT_END_STATE:95 return yaml_parser_parse_document_end(parser, event)96 case yaml_PARSE_BLOCK_NODE_STATE:97 return yaml_parser_parse_node(parser, event, true, false)98 case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:99 return yaml_parser_parse_node(parser, event, true, true)100 case yaml_PARSE_FLOW_NODE_STATE:101 return yaml_parser_parse_node(parser, event, false, false)102 case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:103 return yaml_parser_parse_block_sequence_entry(parser, event, true)104 case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:105 return yaml_parser_parse_block_sequence_entry(parser, event, false)106 case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:107 return yaml_parser_parse_indentless_sequence_entry(parser, event)108 case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:109 return yaml_parser_parse_block_mapping_key(parser, event, true)110 case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:111 return yaml_parser_parse_block_mapping_key(parser, event, false)112 case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:113 return yaml_parser_parse_block_mapping_value(parser, event)114 case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:115 return yaml_parser_parse_flow_sequence_entry(parser, event, true)116 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:117 return yaml_parser_parse_flow_sequence_entry(parser, event, false)118 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:119 return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)120 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:121 return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)122 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:123 return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)124 case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:125 return yaml_parser_parse_flow_mapping_key(parser, event, true)126 case yaml_PARSE_FLOW_MAPPING_KEY_STATE:127 return yaml_parser_parse_flow_mapping_key(parser, event, false)128 case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:129 return yaml_parser_parse_flow_mapping_value(parser, event, false)130 case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:131 return yaml_parser_parse_flow_mapping_value(parser, event, true)132 default:133 panic("invalid parser state")134 }135}136// Parse the production:137// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END138// ************139func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {140 token := peek_token(parser)141 if token == nil {142 return false143 }144 if token.typ != yaml_STREAM_START_TOKEN {145 return yaml_parser_set_parser_error(parser, "did not find expected <stream-start>", token.start_mark)146 }147 parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE148 *event = yaml_event_t{149 typ: yaml_STREAM_START_EVENT,150 start_mark: token.start_mark,151 end_mark: token.end_mark,152 encoding: token.encoding,153 }154 skip_token(parser)155 return true156}157// Parse the productions:158// implicit_document ::= block_node DOCUMENT-END*159// *160// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*161// *************************162func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {163 token := peek_token(parser)164 if token == nil {165 return false166 }167 // Parse extra document end indicators.168 if !implicit {169 for token.typ == yaml_DOCUMENT_END_TOKEN {170 skip_token(parser)171 token = peek_token(parser)172 if token == nil {173 return false174 }175 }176 }177 if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&178 token.typ != yaml_TAG_DIRECTIVE_TOKEN &&179 token.typ != yaml_DOCUMENT_START_TOKEN &&180 token.typ != yaml_STREAM_END_TOKEN {181 // Parse an implicit document.182 if !yaml_parser_process_directives(parser, nil, nil) {183 return false184 }185 parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)186 parser.state = yaml_PARSE_BLOCK_NODE_STATE187 *event = yaml_event_t{188 typ: yaml_DOCUMENT_START_EVENT,189 start_mark: token.start_mark,190 end_mark: token.end_mark,191 }192 } else if token.typ != yaml_STREAM_END_TOKEN {193 // Parse an explicit document.194 var version_directive *yaml_version_directive_t195 var tag_directives []yaml_tag_directive_t196 start_mark := token.start_mark197 if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {198 return false199 }200 token = peek_token(parser)201 if token == nil {202 return false203 }204 if token.typ != yaml_DOCUMENT_START_TOKEN {205 yaml_parser_set_parser_error(parser,206 "did not find expected <document start>", token.start_mark)207 return false208 }209 parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)210 parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE211 end_mark := token.end_mark212 *event = yaml_event_t{213 typ: yaml_DOCUMENT_START_EVENT,214 start_mark: start_mark,215 end_mark: end_mark,216 version_directive: version_directive,217 tag_directives: tag_directives,218 implicit: false,219 }220 skip_token(parser)221 } else {222 // Parse the stream end.223 parser.state = yaml_PARSE_END_STATE224 *event = yaml_event_t{225 typ: yaml_STREAM_END_EVENT,226 start_mark: token.start_mark,227 end_mark: token.end_mark,228 }229 skip_token(parser)230 }231 return true232}233// Parse the productions:234// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*235// ***********236//237func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {238 token := peek_token(parser)239 if token == nil {240 return false241 }242 if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||243 token.typ == yaml_TAG_DIRECTIVE_TOKEN ||244 token.typ == yaml_DOCUMENT_START_TOKEN ||245 token.typ == yaml_DOCUMENT_END_TOKEN ||246 token.typ == yaml_STREAM_END_TOKEN {247 parser.state = parser.states[len(parser.states)-1]248 parser.states = parser.states[:len(parser.states)-1]249 return yaml_parser_process_empty_scalar(parser, event,250 token.start_mark)251 }252 return yaml_parser_parse_node(parser, event, true, false)253}254// Parse the productions:255// implicit_document ::= block_node DOCUMENT-END*256// *************257// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*258//259func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {260 token := peek_token(parser)261 if token == nil {262 return false263 }264 start_mark := token.start_mark265 end_mark := token.start_mark266 implicit := true267 if token.typ == yaml_DOCUMENT_END_TOKEN {268 end_mark = token.end_mark269 skip_token(parser)270 implicit = false271 }272 parser.tag_directives = parser.tag_directives[:0]273 parser.state = yaml_PARSE_DOCUMENT_START_STATE274 *event = yaml_event_t{275 typ: yaml_DOCUMENT_END_EVENT,276 start_mark: start_mark,277 end_mark: end_mark,278 implicit: implicit,279 }280 return true281}282// Parse the productions:283// block_node_or_indentless_sequence ::=284// ALIAS285// *****286// | properties (block_content | indentless_block_sequence)?287// ********** *288// | block_content | indentless_block_sequence289// *290// block_node ::= ALIAS291// *****292// | properties block_content?293// ********** *294// | block_content295// *296// flow_node ::= ALIAS297// *****298// | properties flow_content?299// ********** *300// | flow_content301// *302// properties ::= TAG ANCHOR? | ANCHOR TAG?303// *************************304// block_content ::= block_collection | flow_collection | SCALAR305// ******306// flow_content ::= flow_collection | SCALAR307// ******308func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {309 //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()310 token := peek_token(parser)311 if token == nil {312 return false313 }314 if token.typ == yaml_ALIAS_TOKEN {315 parser.state = parser.states[len(parser.states)-1]316 parser.states = parser.states[:len(parser.states)-1]317 *event = yaml_event_t{318 typ: yaml_ALIAS_EVENT,319 start_mark: token.start_mark,320 end_mark: token.end_mark,321 anchor: token.value,322 }323 skip_token(parser)324 return true325 }326 start_mark := token.start_mark327 end_mark := token.start_mark328 var tag_token bool329 var tag_handle, tag_suffix, anchor []byte330 var tag_mark yaml_mark_t331 if token.typ == yaml_ANCHOR_TOKEN {332 anchor = token.value333 start_mark = token.start_mark334 end_mark = token.end_mark335 skip_token(parser)336 token = peek_token(parser)337 if token == nil {338 return false339 }340 if token.typ == yaml_TAG_TOKEN {341 tag_token = true342 tag_handle = token.value343 tag_suffix = token.suffix344 tag_mark = token.start_mark345 end_mark = token.end_mark346 skip_token(parser)347 token = peek_token(parser)348 if token == nil {349 return false350 }351 }352 } else if token.typ == yaml_TAG_TOKEN {353 tag_token = true354 tag_handle = token.value355 tag_suffix = token.suffix356 start_mark = token.start_mark357 tag_mark = token.start_mark358 end_mark = token.end_mark359 skip_token(parser)360 token = peek_token(parser)361 if token == nil {362 return false363 }364 if token.typ == yaml_ANCHOR_TOKEN {365 anchor = token.value366 end_mark = token.end_mark367 skip_token(parser)368 token = peek_token(parser)369 if token == nil {370 return false371 }372 }373 }374 var tag []byte375 if tag_token {376 if len(tag_handle) == 0 {377 tag = tag_suffix378 tag_suffix = nil379 } else {380 for i := range parser.tag_directives {381 if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {382 tag = append([]byte(nil), parser.tag_directives[i].prefix...)383 tag = append(tag, tag_suffix...)384 break385 }386 }387 if len(tag) == 0 {388 yaml_parser_set_parser_error_context(parser,389 "while parsing a node", start_mark,390 "found undefined tag handle", tag_mark)391 return false392 }393 }394 }395 implicit := len(tag) == 0396 if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {397 end_mark = token.end_mark398 parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE399 *event = yaml_event_t{400 typ: yaml_SEQUENCE_START_EVENT,401 start_mark: start_mark,402 end_mark: end_mark,403 anchor: anchor,404 tag: tag,405 implicit: implicit,406 style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),407 }408 return true409 }410 if token.typ == yaml_SCALAR_TOKEN {411 var plain_implicit, quoted_implicit bool412 end_mark = token.end_mark413 if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {414 plain_implicit = true415 } else if len(tag) == 0 {416 quoted_implicit = true417 }418 parser.state = parser.states[len(parser.states)-1]419 parser.states = parser.states[:len(parser.states)-1]420 *event = yaml_event_t{421 typ: yaml_SCALAR_EVENT,422 start_mark: start_mark,423 end_mark: end_mark,424 anchor: anchor,425 tag: tag,426 value: token.value,427 implicit: plain_implicit,428 quoted_implicit: quoted_implicit,429 style: yaml_style_t(token.style),430 }431 skip_token(parser)432 return true433 }434 if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {435 // [Go] Some of the events below can be merged as they differ only on style.436 end_mark = token.end_mark437 parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE438 *event = yaml_event_t{439 typ: yaml_SEQUENCE_START_EVENT,440 start_mark: start_mark,441 end_mark: end_mark,442 anchor: anchor,443 tag: tag,444 implicit: implicit,445 style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),446 }447 return true448 }449 if token.typ == yaml_FLOW_MAPPING_START_TOKEN {450 end_mark = token.end_mark451 parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE452 *event = yaml_event_t{453 typ: yaml_MAPPING_START_EVENT,454 start_mark: start_mark,455 end_mark: end_mark,456 anchor: anchor,457 tag: tag,458 implicit: implicit,459 style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),460 }461 return true462 }463 if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {464 end_mark = token.end_mark465 parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE466 *event = yaml_event_t{467 typ: yaml_SEQUENCE_START_EVENT,468 start_mark: start_mark,469 end_mark: end_mark,470 anchor: anchor,471 tag: tag,472 implicit: implicit,473 style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),474 }475 return true476 }477 if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {478 end_mark = token.end_mark479 parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE480 *event = yaml_event_t{481 typ: yaml_MAPPING_START_EVENT,482 start_mark: start_mark,483 end_mark: end_mark,484 anchor: anchor,485 tag: tag,486 implicit: implicit,487 style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE),488 }489 return true490 }491 if len(anchor) > 0 || len(tag) > 0 {492 parser.state = parser.states[len(parser.states)-1]493 parser.states = parser.states[:len(parser.states)-1]494 *event = yaml_event_t{495 typ: yaml_SCALAR_EVENT,496 start_mark: start_mark,497 end_mark: end_mark,498 anchor: anchor,499 tag: tag,500 implicit: implicit,501 quoted_implicit: false,502 style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),503 }504 return true505 }506 context := "while parsing a flow node"507 if block {508 context = "while parsing a block node"509 }510 yaml_parser_set_parser_error_context(parser, context, start_mark,511 "did not find expected node content", token.start_mark)512 return false513}514// Parse the productions:515// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END516// ******************** *********** * *********517//518func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {519 if first {520 token := peek_token(parser)521 parser.marks = append(parser.marks, token.start_mark)522 skip_token(parser)523 }524 token := peek_token(parser)525 if token == nil {526 return false527 }528 if token.typ == yaml_BLOCK_ENTRY_TOKEN {529 mark := token.end_mark530 skip_token(parser)531 token = peek_token(parser)532 if token == nil {533 return false534 }535 if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {536 parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)537 return yaml_parser_parse_node(parser, event, true, false)538 } else {539 parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE540 return yaml_parser_process_empty_scalar(parser, event, mark)541 }542 }543 if token.typ == yaml_BLOCK_END_TOKEN {544 parser.state = parser.states[len(parser.states)-1]545 parser.states = parser.states[:len(parser.states)-1]546 parser.marks = parser.marks[:len(parser.marks)-1]547 *event = yaml_event_t{548 typ: yaml_SEQUENCE_END_EVENT,549 start_mark: token.start_mark,550 end_mark: token.end_mark,551 }552 skip_token(parser)553 return true554 }555 context_mark := parser.marks[len(parser.marks)-1]556 parser.marks = parser.marks[:len(parser.marks)-1]557 return yaml_parser_set_parser_error_context(parser,558 "while parsing a block collection", context_mark,559 "did not find expected '-' indicator", token.start_mark)560}561// Parse the productions:562// indentless_sequence ::= (BLOCK-ENTRY block_node?)+563// *********** *564func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {565 token := peek_token(parser)566 if token == nil {567 return false568 }569 if token.typ == yaml_BLOCK_ENTRY_TOKEN {570 mark := token.end_mark571 skip_token(parser)572 token = peek_token(parser)573 if token == nil {574 return false575 }576 if token.typ != yaml_BLOCK_ENTRY_TOKEN &&577 token.typ != yaml_KEY_TOKEN &&578 token.typ != yaml_VALUE_TOKEN &&579 token.typ != yaml_BLOCK_END_TOKEN {580 parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)581 return yaml_parser_parse_node(parser, event, true, false)582 }583 parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE584 return yaml_parser_process_empty_scalar(parser, event, mark)585 }586 parser.state = parser.states[len(parser.states)-1]587 parser.states = parser.states[:len(parser.states)-1]588 *event = yaml_event_t{589 typ: yaml_SEQUENCE_END_EVENT,590 start_mark: token.start_mark,591 end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark?592 }593 return true594}595// Parse the productions:596// block_mapping ::= BLOCK-MAPPING_START597// *******************598// ((KEY block_node_or_indentless_sequence?)?599// *** *600// (VALUE block_node_or_indentless_sequence?)?)*601//602// BLOCK-END603// *********604//605func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {606 if first {607 token := peek_token(parser)608 parser.marks = append(parser.marks, token.start_mark)609 skip_token(parser)610 }611 token := peek_token(parser)612 if token == nil {613 return false614 }615 if token.typ == yaml_KEY_TOKEN {616 mark := token.end_mark617 skip_token(parser)618 token = peek_token(parser)619 if token == nil {620 return false621 }622 if token.typ != yaml_KEY_TOKEN &&623 token.typ != yaml_VALUE_TOKEN &&624 token.typ != yaml_BLOCK_END_TOKEN {625 parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)626 return yaml_parser_parse_node(parser, event, true, true)627 } else {628 parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE629 return yaml_parser_process_empty_scalar(parser, event, mark)630 }631 } else if token.typ == yaml_BLOCK_END_TOKEN {632 parser.state = parser.states[len(parser.states)-1]633 parser.states = parser.states[:len(parser.states)-1]634 parser.marks = parser.marks[:len(parser.marks)-1]635 *event = yaml_event_t{636 typ: yaml_MAPPING_END_EVENT,637 start_mark: token.start_mark,638 end_mark: token.end_mark,639 }640 skip_token(parser)641 return true642 }643 context_mark := parser.marks[len(parser.marks)-1]644 parser.marks = parser.marks[:len(parser.marks)-1]645 return yaml_parser_set_parser_error_context(parser,646 "while parsing a block mapping", context_mark,647 "did not find expected key", token.start_mark)648}649// Parse the productions:650// block_mapping ::= BLOCK-MAPPING_START651//652// ((KEY block_node_or_indentless_sequence?)?653//654// (VALUE block_node_or_indentless_sequence?)?)*655// ***** *656// BLOCK-END657//658//659func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {660 token := peek_token(parser)661 if token == nil {662 return false663 }664 if token.typ == yaml_VALUE_TOKEN {665 mark := token.end_mark666 skip_token(parser)667 token = peek_token(parser)668 if token == nil {669 return false670 }671 if token.typ != yaml_KEY_TOKEN &&672 token.typ != yaml_VALUE_TOKEN &&673 token.typ != yaml_BLOCK_END_TOKEN {674 parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)675 return yaml_parser_parse_node(parser, event, true, true)676 }677 parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE678 return yaml_parser_process_empty_scalar(parser, event, mark)679 }680 parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE681 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)682}683// Parse the productions:684// flow_sequence ::= FLOW-SEQUENCE-START685// *******************686// (flow_sequence_entry FLOW-ENTRY)*687// * **********688// flow_sequence_entry?689// *690// FLOW-SEQUENCE-END691// *****************692// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?693// *694//695func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {696 if first {697 token := peek_token(parser)698 parser.marks = append(parser.marks, token.start_mark)699 skip_token(parser)700 }701 token := peek_token(parser)702 if token == nil {703 return false704 }705 if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {706 if !first {707 if token.typ == yaml_FLOW_ENTRY_TOKEN {708 skip_token(parser)709 token = peek_token(parser)710 if token == nil {711 return false712 }713 } else {714 context_mark := parser.marks[len(parser.marks)-1]715 parser.marks = parser.marks[:len(parser.marks)-1]716 return yaml_parser_set_parser_error_context(parser,717 "while parsing a flow sequence", context_mark,718 "did not find expected ',' or ']'", token.start_mark)719 }720 }721 if token.typ == yaml_KEY_TOKEN {722 parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE723 *event = yaml_event_t{724 typ: yaml_MAPPING_START_EVENT,725 start_mark: token.start_mark,726 end_mark: token.end_mark,727 implicit: true,728 style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),729 }730 skip_token(parser)731 return true732 } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {733 parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)734 return yaml_parser_parse_node(parser, event, false, false)735 }736 }737 parser.state = parser.states[len(parser.states)-1]738 parser.states = parser.states[:len(parser.states)-1]739 parser.marks = parser.marks[:len(parser.marks)-1]740 *event = yaml_event_t{741 typ: yaml_SEQUENCE_END_EVENT,742 start_mark: token.start_mark,743 end_mark: token.end_mark,744 }745 skip_token(parser)746 return true747}748//749// Parse the productions:750// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?751// *** *752//753func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {754 token := peek_token(parser)755 if token == nil {756 return false757 }758 if token.typ != yaml_VALUE_TOKEN &&759 token.typ != yaml_FLOW_ENTRY_TOKEN &&760 token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {761 parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)762 return yaml_parser_parse_node(parser, event, false, false)763 }764 mark := token.end_mark765 skip_token(parser)766 parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE767 return yaml_parser_process_empty_scalar(parser, event, mark)768}769// Parse the productions:770// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?771// ***** *772//773func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {774 token := peek_token(parser)775 if token == nil {776 return false777 }778 if token.typ == yaml_VALUE_TOKEN {779 skip_token(parser)780 token := peek_token(parser)781 if token == nil {782 return false783 }784 if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {785 parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)786 return yaml_parser_parse_node(parser, event, false, false)787 }788 }789 parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE790 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)791}792// Parse the productions:793// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?794// *795//796func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {797 token := peek_token(parser)798 if token == nil {799 return false800 }801 parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE802 *event = yaml_event_t{803 typ: yaml_MAPPING_END_EVENT,804 start_mark: token.start_mark,805 end_mark: token.start_mark, // [Go] Shouldn't this be end_mark?806 }807 return true808}809// Parse the productions:810// flow_mapping ::= FLOW-MAPPING-START811// ******************812// (flow_mapping_entry FLOW-ENTRY)*813// * **********814// flow_mapping_entry?815// ******************816// FLOW-MAPPING-END817// ****************818// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?819// * *** *820//821func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {822 if first {823 token := peek_token(parser)824 parser.marks = append(parser.marks, token.start_mark)825 skip_token(parser)826 }827 token := peek_token(parser)828 if token == nil {829 return false830 }831 if token.typ != yaml_FLOW_MAPPING_END_TOKEN {832 if !first {833 if token.typ == yaml_FLOW_ENTRY_TOKEN {834 skip_token(parser)835 token = peek_token(parser)836 if token == nil {837 return false838 }839 } else {840 context_mark := parser.marks[len(parser.marks)-1]841 parser.marks = parser.marks[:len(parser.marks)-1]842 return yaml_parser_set_parser_error_context(parser,843 "while parsing a flow mapping", context_mark,844 "did not find expected ',' or '}'", token.start_mark)845 }846 }847 if token.typ == yaml_KEY_TOKEN {848 skip_token(parser)849 token = peek_token(parser)850 if token == nil {851 return false852 }853 if token.typ != yaml_VALUE_TOKEN &&854 token.typ != yaml_FLOW_ENTRY_TOKEN &&855 token.typ != yaml_FLOW_MAPPING_END_TOKEN {856 parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)857 return yaml_parser_parse_node(parser, event, false, false)858 } else {859 parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE860 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)861 }862 } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {863 parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)864 return yaml_parser_parse_node(parser, event, false, false)865 }866 }867 parser.state = parser.states[len(parser.states)-1]868 parser.states = parser.states[:len(parser.states)-1]869 parser.marks = parser.marks[:len(parser.marks)-1]870 *event = yaml_event_t{871 typ: yaml_MAPPING_END_EVENT,872 start_mark: token.start_mark,873 end_mark: token.end_mark,874 }875 skip_token(parser)876 return true877}878// Parse the productions:879// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?880// * ***** *881//882func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {883 token := peek_token(parser)884 if token == nil {885 return false886 }887 if empty {888 parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE889 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)890 }891 if token.typ == yaml_VALUE_TOKEN {892 skip_token(parser)893 token = peek_token(parser)894 if token == nil {895 return false896 }897 if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {898 parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)899 return yaml_parser_parse_node(parser, event, false, false)900 }901 }902 parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE903 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)904}905// Generate an empty scalar event.906func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {907 *event = yaml_event_t{908 typ: yaml_SCALAR_EVENT,909 start_mark: mark,910 end_mark: mark,911 value: nil, // Empty912 implicit: true,913 style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),914 }915 return true916}917var default_tag_directives = []yaml_tag_directive_t{918 {[]byte("!"), []byte("!")},919 {[]byte("!!"), []byte("tag:yaml.org,2002:")},920}921// Parse directives.922func yaml_parser_process_directives(parser *yaml_parser_t,923 version_directive_ref **yaml_version_directive_t,924 tag_directives_ref *[]yaml_tag_directive_t) bool {925 var version_directive *yaml_version_directive_t926 var tag_directives []yaml_tag_directive_t927 token := peek_token(parser)928 if token == nil {929 return false930 }931 for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {932 if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {933 if version_directive != nil {934 yaml_parser_set_parser_error(parser,935 "found duplicate %YAML directive", token.start_mark)936 return false937 }938 if token.major != 1 || token.minor != 1 {939 yaml_parser_set_parser_error(parser,940 "found incompatible YAML document", token.start_mark)941 return false942 }943 version_directive = &yaml_version_directive_t{944 major: token.major,945 minor: token.minor,946 }947 } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {948 value := yaml_tag_directive_t{949 handle: token.value,950 prefix: token.prefix,951 }952 if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {953 return false954 }955 tag_directives = append(tag_directives, value)956 }957 skip_token(parser)958 token = peek_token(parser)959 if token == nil {960 return false961 }962 }963 for i := range default_tag_directives {964 if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {965 return false966 }967 }968 if version_directive_ref != nil {969 *version_directive_ref = version_directive970 }971 if tag_directives_ref != nil {972 *tag_directives_ref = tag_directives973 }974 return true975}976// Append a tag directive to the directives stack.977func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {978 for i := range parser.tag_directives {979 if bytes.Equal(value.handle, parser.tag_directives[i].handle) {980 if allow_duplicates {981 return true982 }983 return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)984 }985 }986 // [Go] I suspect the copy is unnecessary. This was likely done987 // because there was no way to track ownership of the data.988 value_copy := yaml_tag_directive_t{989 handle: make([]byte, len(value.handle)),990 prefix: make([]byte, len(value.prefix)),991 }992 copy(value_copy.handle, value.handle)993 copy(value_copy.prefix, value.prefix)994 parser.tag_directives = append(parser.tag_directives, value_copy)995 return true996}...
ConsoleOptionParserTest.php
Source:ConsoleOptionParserTest.php
...27 *28 * @return void29 */30 public function testDescription() {31 $parser = new ConsoleOptionParser('test', false);32 $result = $parser->description('A test');33 $this->assertEquals($parser, $result, 'Setting description is not chainable');34 $this->assertEquals('A test', $parser->description(), 'getting value is wrong.');35 $parser->description(array('A test', 'something'));36 $this->assertEquals("A test\nsomething", $parser->description(), 'getting value is wrong.');37 }38/**39 * test setting the console epilog40 *41 * @return void42 */43 public function testEpilog() {44 $parser = new ConsoleOptionParser('test', false);45 $result = $parser->epilog('A test');46 $this->assertEquals($parser, $result, 'Setting epilog is not chainable');47 $this->assertEquals('A test', $parser->epilog(), 'getting value is wrong.');48 $parser->epilog(array('A test', 'something'));49 $this->assertEquals("A test\nsomething", $parser->epilog(), 'getting value is wrong.');50 }51/**52 * test adding an option returns self.53 *54 * @return void55 */56 public function testAddOptionReturnSelf() {57 $parser = new ConsoleOptionParser('test', false);58 $result = $parser->addOption('test');59 $this->assertEquals($parser, $result, 'Did not return $this from addOption');60 }61/**62 * test adding an option and using the long value for parsing.63 *64 * @return void65 */66 public function testAddOptionLong() {67 $parser = new ConsoleOptionParser('test', false);68 $parser->addOption('test', array(69 'short' => 't'70 ));71 $result = $parser->parse(array('--test', 'value'));72 $this->assertEquals(array('test' => 'value', 'help' => false), $result[0], 'Long parameter did not parse out');73 }74/**75 * test adding an option with a zero value76 *77 * @return void78 */79 public function testAddOptionZero() {80 $parser = new ConsoleOptionParser('test', false);81 $parser->addOption('count', array());82 $result = $parser->parse(array('--count', '0'));83 $this->assertEquals(array('count' => '0', 'help' => false), $result[0], 'Zero parameter did not parse out');84 }85/**86 * test addOption with an object.87 *88 * @return void89 */90 public function testAddOptionObject() {91 $parser = new ConsoleOptionParser('test', false);92 $parser->addOption(new ConsoleInputOption('test', 't'));93 $result = $parser->parse(array('--test=value'));94 $this->assertEquals(array('test' => 'value', 'help' => false), $result[0], 'Long parameter did not parse out');95 }96/**97 * test adding an option and using the long value for parsing.98 *99 * @return void100 */101 public function testAddOptionLongEquals() {102 $parser = new ConsoleOptionParser('test', false);103 $parser->addOption('test', array(104 'short' => 't'105 ));106 $result = $parser->parse(array('--test=value'));107 $this->assertEquals(array('test' => 'value', 'help' => false), $result[0], 'Long parameter did not parse out');108 }109/**110 * test adding an option and using the default.111 *112 * @return void113 */114 public function testAddOptionDefault() {115 $parser = new ConsoleOptionParser('test', false);116 $parser->addOption('test', array(117 'default' => 'default value',118 ));119 $result = $parser->parse(array('--test'));120 $this->assertEquals(array('test' => 'default value', 'help' => false), $result[0], 'Default value did not parse out');121 $parser = new ConsoleOptionParser('test', false);122 $parser->addOption('test', array(123 'default' => 'default value',124 ));125 $result = $parser->parse(array());126 $this->assertEquals(array('test' => 'default value', 'help' => false), $result[0], 'Default value did not parse out');127 }128/**129 * test adding an option and using the short value for parsing.130 *131 * @return void132 */133 public function testAddOptionShort() {134 $parser = new ConsoleOptionParser('test', false);135 $parser->addOption('test', array(136 'short' => 't'137 ));138 $result = $parser->parse(array('-t', 'value'));139 $this->assertEquals(array('test' => 'value', 'help' => false), $result[0], 'Short parameter did not parse out');140 }141/**142 * Test that adding an option using a two letter short value causes an exception.143 * As they will not parse correctly.144 *145 * @expectedException ConsoleException146 * @return void147 */148 public function testAddOptionShortOneLetter() {149 $parser = new ConsoleOptionParser('test', false);150 $parser->addOption('test', array('short' => 'te'));151 }152/**153 * test adding and using boolean options.154 *155 * @return void156 */157 public function testAddOptionBoolean() {158 $parser = new ConsoleOptionParser('test', false);159 $parser->addOption('test', array(160 'boolean' => true,161 ));162 $result = $parser->parse(array('--test', 'value'));163 $expected = array(array('test' => true, 'help' => false), array('value'));164 $this->assertEquals($expected, $result);165 $result = $parser->parse(array('value'));166 $expected = array(array('test' => false, 'help' => false), array('value'));167 $this->assertEquals($expected, $result);168 }169/**170 * test adding an multiple shorts.171 *172 * @return void173 */174 public function testAddOptionMultipleShort() {175 $parser = new ConsoleOptionParser('test', false);176 $parser->addOption('test', array('short' => 't', 'boolean' => true))177 ->addOption('file', array('short' => 'f', 'boolean' => true))178 ->addOption('output', array('short' => 'o', 'boolean' => true));179 $result = $parser->parse(array('-o', '-t', '-f'));180 $expected = array('file' => true, 'test' => true, 'output' => true, 'help' => false);181 $this->assertEquals($expected, $result[0], 'Short parameter did not parse out');182 $result = $parser->parse(array('-otf'));183 $this->assertEquals($expected, $result[0], 'Short parameter did not parse out');184 }185/**186 * test multiple options at once.187 *188 * @return void189 */190 public function testMultipleOptions() {191 $parser = new ConsoleOptionParser('test', false);192 $parser->addOption('test')193 ->addOption('connection')194 ->addOption('table', array('short' => 't', 'default' => true));195 $result = $parser->parse(array('--test', 'value', '-t', '--connection', 'postgres'));196 $expected = array('test' => 'value', 'table' => true, 'connection' => 'postgres', 'help' => false);197 $this->assertEquals($expected, $result[0], 'multiple options did not parse');198 }199/**200 * Test adding multiple options.201 *202 * @return void203 */204 public function testAddOptions() {205 $parser = new ConsoleOptionParser('something', false);206 $result = $parser->addOptions(array(207 'name' => array('help' => 'The name'),208 'other' => array('help' => 'The other arg')209 ));210 $this->assertEquals($parser, $result, 'addOptions is not chainable.');211 $result = $parser->options();212 $this->assertEquals(3, count($result), 'Not enough options');213 }214/**215 * test that boolean options work216 *217 * @return void218 */219 public function testOptionWithBooleanParam() {220 $parser = new ConsoleOptionParser('test', false);221 $parser->addOption('no-commit', array('boolean' => true))222 ->addOption('table', array('short' => 't'));223 $result = $parser->parse(array('--table', 'posts', '--no-commit', 'arg1', 'arg2'));224 $expected = array(array('table' => 'posts', 'no-commit' => true, 'help' => false), array('arg1', 'arg2'));225 $this->assertEquals($expected, $result, 'Boolean option did not parse correctly.');226 }227/**228 * test parsing options that do not exist.229 *230 * @expectedException ConsoleException231 * @return void232 */233 public function testOptionThatDoesNotExist() {234 $parser = new ConsoleOptionParser('test', false);235 $parser->addOption('no-commit', array('boolean' => true));236 $parser->parse(array('--fail', 'other'));237 }238/**239 * test parsing short options that do not exist.240 *241 * @expectedException ConsoleException242 * @return void243 */244 public function testShortOptionThatDoesNotExist() {245 $parser = new ConsoleOptionParser('test', false);246 $parser->addOption('no-commit', array('boolean' => true));247 $parser->parse(array('-f'));248 }249/**250 * test that options with choices enforce them.251 *252 * @expectedException ConsoleException253 * @return void254 */255 public function testOptionWithChoices() {256 $parser = new ConsoleOptionParser('test', false);257 $parser->addOption('name', array('choices' => array('mark', 'jose')));258 $result = $parser->parse(array('--name', 'mark'));259 $expected = array('name' => 'mark', 'help' => false);260 $this->assertEquals($expected, $result[0], 'Got the correct value.');261 $parser->parse(array('--name', 'jimmy'));262 }263/**264 * Ensure that option values can start with -265 *266 * @return void267 */268 public function testOptionWithValueStartingWithMinus() {269 $parser = new ConsoleOptionParser('test', false);270 $parser->addOption('name')271 ->addOption('age');272 $result = $parser->parse(array('--name', '-foo', '--age', 'old'));273 $expected = array('name' => '-foo', 'age' => 'old', 'help' => false);274 $this->assertEquals($expected, $result[0], 'Option values starting with "-" are broken.');275 }276/**277 * test positional argument parsing.278 *279 * @return void280 */281 public function testPositionalArgument() {282 $parser = new ConsoleOptionParser('test', false);283 $result = $parser->addArgument('name', array('help' => 'An argument'));284 $this->assertEquals($parser, $result, 'Should return this');285 }286/**287 * test addOption with an object.288 *289 * @return void290 */291 public function testAddArgumentObject() {292 $parser = new ConsoleOptionParser('test', false);293 $parser->addArgument(new ConsoleInputArgument('test'));294 $result = $parser->arguments();295 $this->assertCount(1, $result);296 $this->assertEquals('test', $result[0]->name());297 }298/**299 * Test adding arguments out of order.300 *301 * @return void302 */303 public function testAddArgumentOutOfOrder() {304 $parser = new ConsoleOptionParser('test', false);305 $parser->addArgument('name', array('index' => 1, 'help' => 'first argument'))306 ->addArgument('bag', array('index' => 2, 'help' => 'second argument'))307 ->addArgument('other', array('index' => 0, 'help' => 'Zeroth argument'));308 $result = $parser->arguments();309 $this->assertCount(3, $result);310 $this->assertEquals('other', $result[0]->name());311 $this->assertEquals('name', $result[1]->name());312 $this->assertEquals('bag', $result[2]->name());313 $this->assertSame(array(0, 1, 2), array_keys($result));314 }315/**316 * test overwriting positional arguments.317 *318 * @return void319 */320 public function testPositionalArgOverwrite() {321 $parser = new ConsoleOptionParser('test', false);322 $parser->addArgument('name', array('help' => 'An argument'))323 ->addArgument('other', array('index' => 0));324 $result = $parser->arguments();325 $this->assertEquals(1, count($result), 'Overwrite did not occur');326 }327/**328 * test parsing arguments.329 *330 * @expectedException ConsoleException331 * @return void332 */333 public function testParseArgumentTooMany() {334 $parser = new ConsoleOptionParser('test', false);335 $parser->addArgument('name', array('help' => 'An argument'))336 ->addArgument('other');337 $expected = array('one', 'two');338 $result = $parser->parse($expected);339 $this->assertEquals($expected, $result[1], 'Arguments are not as expected');340 $parser->parse(array('one', 'two', 'three'));341 }342/**343 * test parsing arguments with 0 value.344 *345 * @return void346 */347 public function testParseArgumentZero() {348 $parser = new ConsoleOptionParser('test', false);349 $expected = array('one', 'two', 0, 'after', 'zero');350 $result = $parser->parse($expected);351 $this->assertEquals($expected, $result[1], 'Arguments are not as expected');352 }353/**354 * test that when there are not enough arguments an exception is raised355 *356 * @expectedException ConsoleException357 * @return void358 */359 public function testPositionalArgNotEnough() {360 $parser = new ConsoleOptionParser('test', false);361 $parser->addArgument('name', array('required' => true))362 ->addArgument('other', array('required' => true));363 $parser->parse(array('one'));364 }365/**366 * test that arguments with choices enforce them.367 *368 * @expectedException ConsoleException369 * @return void370 */371 public function testPositionalArgWithChoices() {372 $parser = new ConsoleOptionParser('test', false);373 $parser->addArgument('name', array('choices' => array('mark', 'jose')))374 ->addArgument('alias', array('choices' => array('cowboy', 'samurai')))375 ->addArgument('weapon', array('choices' => array('gun', 'sword')));376 $result = $parser->parse(array('mark', 'samurai', 'sword'));377 $expected = array('mark', 'samurai', 'sword');378 $this->assertEquals($expected, $result[1], 'Got the correct value.');379 $parser->parse(array('jose', 'coder'));380 }381/**382 * Test adding multiple arguments.383 *384 * @return void385 */386 public function testAddArguments() {387 $parser = new ConsoleOptionParser('test', false);388 $result = $parser->addArguments(array(389 'name' => array('help' => 'The name'),390 'other' => array('help' => 'The other arg')391 ));392 $this->assertEquals($parser, $result, 'addArguments is not chainable.');393 $result = $parser->arguments();394 $this->assertEquals(2, count($result), 'Not enough arguments');395 }396/**397 * test setting a subcommand up.398 *399 * @return void400 */401 public function testSubcommand() {402 $parser = new ConsoleOptionParser('test', false);403 $result = $parser->addSubcommand('initdb', array(404 'help' => 'Initialize the database'405 ));406 $this->assertEquals($parser, $result, 'Adding a subcommand is not chainable');407 }408/**409 * test addSubcommand with an object.410 *411 * @return void412 */413 public function testAddSubcommandObject() {414 $parser = new ConsoleOptionParser('test', false);415 $parser->addSubcommand(new ConsoleInputSubcommand('test'));416 $result = $parser->subcommands();417 $this->assertEquals(1, count($result));418 $this->assertEquals('test', $result['test']->name());419 }420/**421 * test removeSubcommand with an object.422 *423 * @return void424 */425 public function testRemoveSubcommand() {426 $parser = new ConsoleOptionParser('test', false);427 $parser->addSubcommand(new ConsoleInputSubcommand('test'));428 $result = $parser->subcommands();429 $this->assertEquals(1, count($result));430 $parser->removeSubcommand('test');431 $result = $parser->subcommands();432 $this->assertEquals(0, count($result), 'Remove a subcommand does not work');433 }434/**435 * test adding multiple subcommands436 *437 * @return void438 */439 public function testAddSubcommands() {440 $parser = new ConsoleOptionParser('test', false);441 $result = $parser->addSubcommands(array(442 'initdb' => array('help' => 'Initialize the database'),443 'create' => array('help' => 'Create something')444 ));445 $this->assertEquals($parser, $result, 'Adding a subcommands is not chainable');446 $result = $parser->subcommands();447 $this->assertEquals(2, count($result), 'Not enough subcommands');448 }449/**450 * test that no exception is triggered when help is being generated451 *452 * @return void453 */454 public function testHelpNoExceptionWhenGettingHelp() {455 $parser = new ConsoleOptionParser('mycommand', false);456 $parser->addOption('test', array('help' => 'A test option.'))457 ->addArgument('model', array('help' => 'The model to make.', 'required' => true));458 $result = $parser->parse(array('--help'));459 $this->assertTrue($result[0]['help']);460 }461/**462 * test that help() with a command param shows the help for a subcommand463 *464 * @return void465 */466 public function testHelpSubcommandHelp() {467 $subParser = new ConsoleOptionParser('method', false);468 $subParser->addOption('connection', array('help' => 'Db connection.'));469 $parser = new ConsoleOptionParser('mycommand', false);470 $parser->addSubcommand('method', array(471 'help' => 'This is another command',472 'parser' => $subParser473 ))474 ->addOption('test', array('help' => 'A test option.'));475 $result = $parser->help('method');476 $expected = <<<TEXT477<info>Usage:</info>478cake mycommand method [-h] [--connection]479<info>Options:</info>480--help, -h Display this help.481--connection Db connection.482TEXT;483 $this->assertTextEquals($expected, $result, 'Help is not correct.');484 }485/**486 * test building a parser from an array.487 *488 * @return void489 */490 public function testBuildFromArray() {491 $spec = array(492 'command' => 'test',493 'arguments' => array(494 'name' => array('help' => 'The name'),495 'other' => array('help' => 'The other arg')496 ),497 'options' => array(498 'name' => array('help' => 'The name'),499 'other' => array('help' => 'The other arg')500 ),501 'subcommands' => array(502 'initdb' => array('help' => 'make database')503 ),504 'description' => 'description text',505 'epilog' => 'epilog text'506 );507 $parser = ConsoleOptionParser::buildFromArray($spec);508 $this->assertEquals($spec['description'], $parser->description());509 $this->assertEquals($spec['epilog'], $parser->epilog());510 $options = $parser->options();511 $this->assertTrue(isset($options['name']));512 $this->assertTrue(isset($options['other']));513 $args = $parser->arguments();514 $this->assertEquals(2, count($args));515 $commands = $parser->subcommands();516 $this->assertEquals(1, count($commands));517 }518/**519 * test that create() returns instances520 *521 * @return void522 */523 public function testCreateFactory() {524 $parser = ConsoleOptionParser::create('factory', false);525 $this->assertInstanceOf('ConsoleOptionParser', $parser);526 $this->assertEquals('factory', $parser->command());527 }528/**529 * test that command() inflects the command name.530 *531 * @return void532 */533 public function testCommandInflection() {534 $parser = new ConsoleOptionParser('CommandLine');535 $this->assertEquals('command_line', $parser->command());536 }537/**538 * test that parse() takes a subcommand argument, and that the subcommand parser539 * is used.540 *541 * @return void542 */543 public function testParsingWithSubParser() {544 $parser = new ConsoleOptionParser('test', false);545 $parser->addOption('primary')546 ->addArgument('one', array('required' => true, 'choices' => array('a', 'b')))547 ->addArgument('two', array('required' => true))548 ->addSubcommand('sub', array(549 'parser' => array(550 'options' => array(551 'secondary' => array('boolean' => true),552 'fourth' => array('help' => 'fourth option')553 ),554 'arguments' => array(555 'sub_arg' => array('choices' => array('c', 'd'))556 )557 )558 ));559 $result = $parser->parse(array('--secondary', '--fourth', '4', 'c'), 'sub');560 $expected = array(array(561 'secondary' => true,562 'fourth' => '4',563 'help' => false,564 'verbose' => false,565 'quiet' => false), array('c'));566 $this->assertEquals($expected, $result, 'Sub parser did not parse request.');567 }568}...
JavaScriptSymbol.php
Source:JavaScriptSymbol.php
...113 }114 throw new Exception("No class for {$this->id}:{$this->arity}");115 }116 // led/nud/lbp functions117 public function led_bracket($parser, $left) {118 $this->first = $left;119 $this->second = $parser->expression();120 $this->arity = 'binary';121 $parser->advance(']');122 return $this;123 }124 public function nud_bracket($parser) {125 $items = array();126 if (!$parser->peek(']')) {127 while (1) {128 $items[] = $parser->expression();129 if (!$parser->peek(',')) {130 break;131 }132 $parser->advance(',');133 if ($parser->peek(']')) {134 // Be lenient about trailing commas135 break;136 }137 }138 }139 $parser->advance(']');140 $this->first = $items;141 $this->arity = 'unary';142 return $this;143 }144 public function std_break($parser) {145 $parser->skip_terminators();146 $this->arity = 'statement';147 return $this;148 }149 public function lbp_colon($parser, $left) {150 if ($left->arity == 'name' && $parser->peek2(array('for', 'while', 'do'))) {151 return 100;152 }153 return 0;154 }155 public function led_colon($parser, $left) {156 $this->first = $left;157 if ($parser->token->arity != 'name') {158 throw new Exception("Line {$left->line_number}, char {$left->char_pos}: Expected a property name");159 }160 $parser->token->arity = 'literal';161 $this->second = $parser->expression();162 $this->arity = 'binary';163 $parser->skip_terminators();164 return $this;165 }166 public function lbp_crement($parser, $left) {167 if ($left->id == '.' || $left->id == '[' || $left->arity == 'name') {168 return 100;169 }170 return 0;171 }172 public function led_crement($parser, $left) {173 // Show that the in/decrementer is on the right174 $this->first = $left;175 $this->arity = 'unary';176 return $this;177 }178 public function nud_crement($parser) {179 // Show that the in/decrement is before the expression180 $this->first = NULL;181 $this->second = $parser->expression(75);182 return $this;183 }184 public function nud_curly($parser) {185 $values = array();186 $this->comments = array();187 if (!$parser->peek('}')) {188 while (1) {189 $token = $parser->token;190 if ($token->arity != 'name' && $token->arity != 'literal') {191 throw new Exception("Line {$token->line_number}, char {$token->char_pos}: Bad key: {$token->id}");192 }193 $comments = $parser->comments_before($token);194 if (!empty($comments)) {195 if (!empty($this->comments)) {196 $this->comments[] = "\n";197 }198 $this->comments = array_merge($this->comments, $comments);199 }200 $parser->advance();201 $parser->advance(':');202 $expression = $parser->expression();203 if (is_array($expression)) {204 $expression = $expression[0];205 }206 $expression->key = $token->value;207 $values[] = $expression;208 if (!$parser->peek(',')) {209 break;210 }211 $token = $parser->token;212 $parser->advance(',');213 if ($parser->peek('}')) {214 // Be lenient about trailing commas215 break;216 }217 }218 }219 if ($parser->peek('}')) {220 $this->comments = array_merge($this->comments, $parser->comments_before($parser->token));221 }222 $parser->advance('}');223 $this->first = $values;224 $this->arity = 'unary';225 return $this;226 }227 public function std_curly($parser) {228 $statements = $parser->statements(array('}'));229 $parser->advance('}');230 return $statements;231 }232 public function std_do($parser) {233 if ($parser->peek('{')) {234 $this->first = $this->block($parser);235 }236 else {237 $this->first = $parser->expression($parser);238 $parser->skip_terminators();239 }240 $parser->advance('while');241 $parser->advance('(');242 $this->second = $parser->expression();243 $parser->advance(')');244 $parser->skip_terminators();245 return $this;246 }247 public function led_equals($parser, $left) {248 $this->first = $left;249 $this->second = $parser->expression(9);250 $parser->scope->assignment($this->first, $this->second);251 return $this;252 }253 public function std_for($parser) {254 $parser->advance('(');255 if($parser->peek('var')) {256 $token = $parser->token;257 $parser->advance('var');258 $this->first = $token->std($parser);259 if ($parser->peek('in')) {260 $parser->advance('in');261 $this->second = $parser->expression();262 }263 }264 else {265 // Don't forget that expressionless for(;;) loops are valid266 $this->first = $parser->peek(';') ? NULL : $parser->statements(array(')', ';'));267 }268 if (!$parser->peek(')')) {269 // var can possibly swallow the ;270 if ($parser->peek(';')) {271 $parser->advance(';');272 }273 $this->second = $parser->peek(';') ? NULL : $parser->statements(array(';'));274 $parser->advance(';');275 $this->thid = $parser->peek(')') ? NULL : $parser->statements(array(')'));276 }277 $parser->advance(')');278 if ($parser->peek('{')) {279 $this->block = $this->block($parser);280 }281 elseif (!$parser->peek(';')) {282 $this->block = $parser->expression();283 }284 $parser->skip_terminators();285 $this->arity = 'statement';286 return $this;287 }288 public function nud_function($parser) {289 $arguments = array();290 $parser->new_scope();291 $this->scope = $parser->scope;292 if ($parser->token->arity == 'name') {293 $parser->scope->define($parser->token);294 $this->name = $parser->token->value;295 $parser->advance();296 }297 $parser->advance('(');298 if (!$parser->peek(')')) {299 while (1) {300 if ($parser->token->arity != 'name') {301 throw new Exception('Expected a parameter name');302 }303 $parser->scope->define($parser->token);304 $argument = $parser->token;305 $parser->advance();306 $argument->comments = array_merge($parser->comments_before($argument), $parser->comments_after($argument));307 $arguments[] = $argument;308 if (!$parser->peek(',')) {309 break;310 }311 $parser->advance(',');312 }313 }314 $this->first = $arguments;315 $parser->advance(')');316 $parser->peek('{');317 $this->comments = $parser->comments_after($parser->token);318 $parser->advance('{');319 $this->second = $parser->statements(array('}'));320 $parser->advance('}');321 $this->arity = 'function';322 $parser->scope_pop();323 return $this;324 }325 public function std_if($parser) {326 $parser->advance('(');327 $this->first = $parser->expression();328 $parser->advance(')');329 if ($parser->peek('{')) {330 $this->second = $this->block($parser);331 }332 elseif (!$parser->peek(';')) {333 $this->second = $parser->expression();334 }335 $parser->skip_terminators();336 337 if ($parser->peek('else')) {338 $parser->advance('else');339 if ($parser->peek('if')) {340 $this->third = $parser->statement;341 }342 elseif ($parser->peek('{')) {343 $this->third = $this->block($parser);344 }345 elseif (!$parser->peek(';')) {346 $this->third = $parser->expression();347 }348 $parser->skip_terminators();349 }350 else {351 $this->third = NULL;352 }353 $this->arity = 'statement';354 return $this;355 }356 public function executed_function($function, $parser) {357 // The function gets executed358 if ($parser->peek('(')) {359 // led_parenthesis might have already swallowed it360 $parser->advance('(');361 }362 $arguments = array();363 if (!$parser->peek(')')) {364 while (1) {365 $arguments[] = $parser->expression();366 if (!$parser->peek(',')) {367 break;368 }369 $parser->advance(',');370 }371 }372 $parser->advance(')');373 $parser->skip_terminators();374 // Make assignments within the function scope (in $function)375 // between the arguments in the expression and the passed arguments376 foreach ($function->first as $i => $parameter) {377 if ($arguments[$i]) {378 // The passed argument is assigned immediately to the matching parameter379 $function->scope->assignment($parameter, $arguments[$i]);380 }381 }382 $this->first = $function;383 $this->second = $arguments;384 $this->arity = 'execution';385 return $this;386 }387 public function led_parenthesis($parser, $left) {388 if ($left->id == 'function') {389 return $this->executed_function($left, $parser);390 }391 if ($left->id == '{') {392 $expression = $parser->expression();393 $parser->advance(')');394 return $expression;395 }396 if (!$parser->peek(')')) {397 while (1) {398 $arguments[] = $parser->expression();399 if (!$parser->peek(',')) {400 break;401 }402 $parser->advance(',');403 }404 }405 if ($left->arity == 'operator' && $left->id != '.' && $left->id != '[' && count($arguments) == 1) {406 $arguments = $arguments[0];407 }408 // e.g. foo(bar) has a foo first, [bar] second409 $this->arity = 'binary';410 $this->first = $left;411 $this->second = $arguments;412 $parser->advance(')');413 return $this;414 }415 public function nud_parenthesis($parser) {416 // '(' can mean function call, or executed function417 $is_function = $parser->peek('function');418 $expressions = array();419 while (1) {420 $expressions[] = $parser->expression();421 if ($parser->peek(')')) {422 break;423 }424 $parser->advance(',');425 }426 $parser->advance(')');427 if ($is_function && $parser->peek('(')) {428 return $this->executed_function($expressions[0], $parser);429 }430 return $expressions;431 }432 public function led_period($parser, $left) {433 $this->first = $left;434 if ($parser->token->arity != 'name') {435 throw new Exception('Expected a property name');436 }437 $parser->token->arity = 'literal';438 $this->second = $parser->token;439 $this->arity ='binary';440 $parser->advance();441 return $this;442 }443 public function led_questionmark($parser, $left) {444 $this->first = $left;445 $this->second = $parser->expression();446 $parser->advance(':');447 $this->third = $parser->expression();448 $this->arity = 'ternary';449 return $this;450 }451 public function nud_this($parser) {452 $parser->scope->reserve($this);453 $this->arity = 'this';454 return $this;455 }456 public function std_try($parser) {457 $this->first = $this->block($parser);458 if ($parser->peek('catch')) {459 $parser->advance('catch');460 $catch = $parser->new_symbol('catch');461 $parser->advance('(');462 $catch->first = $parser->expression();463 $parser->advance(')');464 $catch->second = $this->block($parser);465 $this->second = $catch;466 }467 if ($parser->peek('finally')) {468 $parser->advance('finally');469 $this->third = $this->block($parser);470 }471 $parser->skip_terminators();472 $this->arity = 'statement';473 return $this;474 }475 public function std_return($parser) {476 if (!$parser->peek("\n") && !$parser->peek(';') && !$parser->peek('}')) {477 $this->first = $parser->expression();478 }479 $parser->skip_terminators();480 $this->arity = 'statement';481 return $this;482 }483 public function std_switch($parser) {484 // switch statements can have multiple485 // levels of passthrough and expressions486 // need to be aggregated for each current487 // case statement until a break is reached488 $branches = array();489 $parser->advance('(');490 $this->first = $parser->expression();491 $parser->advance(')');492 $parser->advance('{');493 $this->second = array();494 $cases = array();495 while (1) {496 if ($parser->peek('}')) {497 break;498 }499 if ($parser->peek('default')) {500 $cases[] = $parser->token;501 $switch = 'default';502 $parser->advance('default');503 }504 else {505 $cases[] = $parser->token;506 $parser->advance('case');507 $switch = 'case';508 $cases[] = $parser->expression();509 }510 $parser->advance(':');511 $statements = $parser->statements(array('default', 'case', '}'));512 if ($switch == 'default') {513 $default = $parser->new_symbol('default');514 $default->first = $statements;515 $cases[] = $default;516 }517 elseif ($switch == 'case' && !empty($statements)) {518 $case = $parser->new_symbol('case');519 $case->first = $statements;520 $cases[] = $case;521 }522 }523 $this->second = $cases;524 $parser->advance('}');525 $this->arity = 'statement';526 return $this;527 }528 public function std_var($parser) {529 $assignments = array();530 while (1) {531 $parser->peek();532 $token = $parser->token;533 if ($token->arity != 'name') {534 throw new Exception("Line {$token->line_number}, char {$token->char_pos}: Expected a new variable name");535 }536 $parser->scope->define($token);537 $parser->advance();538 if ($parser->peek('=')) {539 $t = $parser->token;540 $parser->advance('=');541 $t->first = $token;542 $t->second = $parser->expression();543 $parser->scope->assignment($t->first, $t->second);544 $t->arity = 'binary';545 $assignments[] = $t;546 }547 else {548 $t = $parser->new_symbol('=');549 $t->first = $token;550 $t->second = NULL;551 $assignments[] = $t;552 }553 if (!$parser->peek(',')) {554 break;555 }556 $parser->advance(',');557 }558 $parser->skip_terminators();559 return $assignments;560 }561 public function std_while($parser) {562 $parser->advance('(');563 $this->first = $parser->statements(array(')'));564 $parser->advance(')');565 if ($parser->peek('{')) {566 $this->second = $this->block($parser);567 }568 else {569 $this->second = $parser->expression();570 }571 $parser->skip_terminators();572 $this->arity = 'statement';573 return $this;574 }575}...
Autoloader.php
Source:Autoloader.php
1<?php2namespace PhpParser;3/**4 * @codeCoverageIgnore5 */6class Autoloader7{8 /** @var bool Whether the autoloader has been registered. */9 private static $registered = false;10 /** @var bool Whether we're running on PHP 7. */11 private static $runningOnPhp7;12 /**13 * Registers PhpParser\Autoloader as an SPL autoloader.14 *15 * @param bool $prepend Whether to prepend the autoloader instead of appending16 */17 static public function register($prepend = false) {18 if (self::$registered === true) {19 return;20 }21 spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);22 self::$registered = true;23 self::$runningOnPhp7 = version_compare(PHP_VERSION, '7.0-dev', '>=');24 }25 /**26 * Handles autoloading of classes.27 *28 * @param string $class A class name.29 */30 static public function autoload($class) {31 if (0 === strpos($class, 'PhpParser\\')) {32 if (isset(self::$php7AliasesOldToNew[$class])) {33 if (self::$runningOnPhp7) {34 return;35 }36 // Load the new class, alias will be registered afterwards37 $class = self::$php7AliasesOldToNew[$class];38 }39 $fileName = dirname(__DIR__) . '/' . strtr($class, '\\', '/') . '.php';40 if (file_exists($fileName)) {41 require $fileName;42 }43 if (isset(self::$php7AliasesNewToOld[$class])) {44 // New class name was used, register alias for old one, otherwise45 // it won't be usable in "instanceof" and other non-autoloading places.46 if (!self::$runningOnPhp7) {47 class_alias($class, self::$php7AliasesNewToOld[$class]);48 }49 }50 } else if (0 === strpos($class, 'PHPParser_')) {51 if (isset(self::$nonNamespacedAliases[$class])) {52 // Register all aliases at once to avoid dependency issues53 self::registerNonNamespacedAliases();54 }55 }56 }57 private static function registerNonNamespacedAliases() {58 foreach (self::$nonNamespacedAliases as $old => $new) {59 class_alias($new, $old);60 }61 }62 private static $php7AliasesOldToNew = array(63 'PhpParser\Node\Expr\Cast\Bool' => 'PhpParser\Node\Expr\Cast\Bool_',64 'PhpParser\Node\Expr\Cast\Int' => 'PhpParser\Node\Expr\Cast\Int_',65 'PhpParser\Node\Expr\Cast\Object' => 'PhpParser\Node\Expr\Cast\Object_',66 'PhpParser\Node\Expr\Cast\String' => 'PhpParser\Node\Expr\Cast\String_',67 'PhpParser\Node\Scalar\String' => 'PhpParser\Node\Scalar\String_',68 );69 private static $php7AliasesNewToOld = array(70 'PhpParser\Node\Expr\Cast\Bool_' => 'PhpParser\Node\Expr\Cast\Bool',71 'PhpParser\Node\Expr\Cast\Int_' => 'PhpParser\Node\Expr\Cast\Int',72 'PhpParser\Node\Expr\Cast\Object_' => 'PhpParser\Node\Expr\Cast\Object',73 'PhpParser\Node\Expr\Cast\String_' => 'PhpParser\Node\Expr\Cast\String',74 'PhpParser\Node\Scalar\String_' => 'PhpParser\Node\Scalar\String',75 );76 private static $nonNamespacedAliases = array(77 'PHPParser_Builder' => 'PhpParser\Builder',78 'PHPParser_BuilderAbstract' => 'PhpParser\BuilderAbstract',79 'PHPParser_BuilderFactory' => 'PhpParser\BuilderFactory',80 'PHPParser_Comment' => 'PhpParser\Comment',81 'PHPParser_Comment_Doc' => 'PhpParser\Comment\Doc',82 'PHPParser_Error' => 'PhpParser\Error',83 'PHPParser_Lexer' => 'PhpParser\Lexer',84 'PHPParser_Lexer_Emulative' => 'PhpParser\Lexer\Emulative',85 'PHPParser_Node' => 'PhpParser\Node',86 'PHPParser_NodeAbstract' => 'PhpParser\NodeAbstract',87 'PHPParser_NodeDumper' => 'PhpParser\NodeDumper',88 'PHPParser_NodeTraverser' => 'PhpParser\NodeTraverser',89 'PHPParser_NodeTraverserInterface' => 'PhpParser\NodeTraverserInterface',90 'PHPParser_NodeVisitor' => 'PhpParser\NodeVisitor',91 'PHPParser_NodeVisitor_NameResolver' => 'PhpParser\NodeVisitor\NameResolver',92 'PHPParser_NodeVisitorAbstract' => 'PhpParser\NodeVisitorAbstract',93 'PHPParser_Parser' => 'PhpParser\Parser',94 'PHPParser_PrettyPrinterAbstract' => 'PhpParser\PrettyPrinterAbstract',95 'PHPParser_PrettyPrinter_Default' => 'PhpParser\PrettyPrinter\Standard',96 'PHPParser_PrettyPrinter_Zend' => 'PhpParser\PrettyPrinter\Standard',97 'PHPParser_Serializer' => 'PhpParser\Serializer',98 'PHPParser_Serializer_XML' => 'PhpParser\Serializer\XML',99 'PHPParser_Unserializer' => 'PhpParser\Unserializer',100 'PHPParser_Unserializer_XML' => 'PhpParser\Unserializer\XML',101 'PHPParser_Builder_Class' => 'PhpParser\Builder\Class_',102 'PHPParser_Builder_Function' => 'PhpParser\Builder\Function_',103 'PHPParser_Builder_Interface' => 'PhpParser\Builder\Interface_',104 'PHPParser_Builder_Method' => 'PhpParser\Builder\Method',105 'PHPParser_Builder_Param' => 'PhpParser\Builder\Param',106 'PHPParser_Builder_Property' => 'PhpParser\Builder\Property',107 'PHPParser_Node_Arg' => 'PhpParser\Node\Arg',108 'PHPParser_Node_Const' => 'PhpParser\Node\Const_',109 'PHPParser_Node_Expr' => 'PhpParser\Node\Expr',110 'PHPParser_Node_Name' => 'PhpParser\Node\Name',111 'PHPParser_Node_Name_FullyQualified' => 'PhpParser\Node\Name\FullyQualified',112 'PHPParser_Node_Name_Relative' => 'PhpParser\Node\Name\Relative',113 'PHPParser_Node_Param' => 'PhpParser\Node\Param',114 'PHPParser_Node_Scalar' => 'PhpParser\Node\Scalar',115 'PHPParser_Node_Stmt' => 'PhpParser\Node\Stmt',116 'PHPParser_Node_Stmt_Break' => 'PhpParser\Node\Stmt\Break_',117 'PHPParser_Node_Stmt_Case' => 'PhpParser\Node\Stmt\Case_',118 'PHPParser_Node_Stmt_Catch' => 'PhpParser\Node\Stmt\Catch_',119 'PHPParser_Node_Stmt_Class' => 'PhpParser\Node\Stmt\Class_',120 'PHPParser_Node_Stmt_ClassConst' => 'PhpParser\Node\Stmt\ClassConst',121 'PHPParser_Node_Stmt_ClassMethod' => 'PhpParser\Node\Stmt\ClassMethod',122 'PHPParser_Node_Stmt_Const' => 'PhpParser\Node\Stmt\Const_',123 'PHPParser_Node_Stmt_Continue' => 'PhpParser\Node\Stmt\Continue_',124 'PHPParser_Node_Stmt_Declare' => 'PhpParser\Node\Stmt\Declare_',125 'PHPParser_Node_Stmt_DeclareDeclare' => 'PhpParser\Node\Stmt\DeclareDeclare',126 'PHPParser_Node_Stmt_Do' => 'PhpParser\Node\Stmt\Do_',127 'PHPParser_Node_Stmt_Echo' => 'PhpParser\Node\Stmt\Echo_',128 'PHPParser_Node_Stmt_Else' => 'PhpParser\Node\Stmt\Else_',129 'PHPParser_Node_Stmt_ElseIf' => 'PhpParser\Node\Stmt\ElseIf_',130 'PHPParser_Node_Stmt_For' => 'PhpParser\Node\Stmt\For_',131 'PHPParser_Node_Stmt_Foreach' => 'PhpParser\Node\Stmt\Foreach_',132 'PHPParser_Node_Stmt_Function' => 'PhpParser\Node\Stmt\Function_',133 'PHPParser_Node_Stmt_Global' => 'PhpParser\Node\Stmt\Global_',134 'PHPParser_Node_Stmt_Goto' => 'PhpParser\Node\Stmt\Goto_',135 'PHPParser_Node_Stmt_HaltCompiler' => 'PhpParser\Node\Stmt\HaltCompiler',136 'PHPParser_Node_Stmt_If' => 'PhpParser\Node\Stmt\If_',137 'PHPParser_Node_Stmt_InlineHTML' => 'PhpParser\Node\Stmt\InlineHTML',138 'PHPParser_Node_Stmt_Interface' => 'PhpParser\Node\Stmt\Interface_',139 'PHPParser_Node_Stmt_Label' => 'PhpParser\Node\Stmt\Label',140 'PHPParser_Node_Stmt_Namespace' => 'PhpParser\Node\Stmt\Namespace_',141 'PHPParser_Node_Stmt_Property' => 'PhpParser\Node\Stmt\Property',142 'PHPParser_Node_Stmt_PropertyProperty' => 'PhpParser\Node\Stmt\PropertyProperty',143 'PHPParser_Node_Stmt_Return' => 'PhpParser\Node\Stmt\Return_',144 'PHPParser_Node_Stmt_Static' => 'PhpParser\Node\Stmt\Static_',145 'PHPParser_Node_Stmt_StaticVar' => 'PhpParser\Node\Stmt\StaticVar',146 'PHPParser_Node_Stmt_Switch' => 'PhpParser\Node\Stmt\Switch_',147 'PHPParser_Node_Stmt_Throw' => 'PhpParser\Node\Stmt\Throw_',148 'PHPParser_Node_Stmt_Trait' => 'PhpParser\Node\Stmt\Trait_',149 'PHPParser_Node_Stmt_TraitUse' => 'PhpParser\Node\Stmt\TraitUse',150 'PHPParser_Node_Stmt_TraitUseAdaptation' => 'PhpParser\Node\Stmt\TraitUseAdaptation',151 'PHPParser_Node_Stmt_TraitUseAdaptation_Alias' => 'PhpParser\Node\Stmt\TraitUseAdaptation\Alias',152 'PHPParser_Node_Stmt_TraitUseAdaptation_Precedence' => 'PhpParser\Node\Stmt\TraitUseAdaptation\Precedence',153 'PHPParser_Node_Stmt_TryCatch' => 'PhpParser\Node\Stmt\TryCatch',154 'PHPParser_Node_Stmt_Unset' => 'PhpParser\Node\Stmt\Unset_',155 'PHPParser_Node_Stmt_UseUse' => 'PhpParser\Node\Stmt\UseUse',156 'PHPParser_Node_Stmt_Use' => 'PhpParser\Node\Stmt\Use_',157 'PHPParser_Node_Stmt_While' => 'PhpParser\Node\Stmt\While_',158 'PHPParser_Node_Expr_AssignBitwiseAnd' => 'PhpParser\Node\Expr\AssignOp\BitwiseAnd',159 'PHPParser_Node_Expr_AssignBitwiseOr' => 'PhpParser\Node\Expr\AssignOp\BitwiseOr',160 'PHPParser_Node_Expr_AssignBitwiseXor' => 'PhpParser\Node\Expr\AssignOp\BitwiseXor',161 'PHPParser_Node_Expr_AssignConcat' => 'PhpParser\Node\Expr\AssignOp\Concat',162 'PHPParser_Node_Expr_AssignDiv' => 'PhpParser\Node\Expr\AssignOp\Div',163 'PHPParser_Node_Expr_AssignMinus' => 'PhpParser\Node\Expr\AssignOp\Minus',164 'PHPParser_Node_Expr_AssignMod' => 'PhpParser\Node\Expr\AssignOp\Mod',165 'PHPParser_Node_Expr_AssignMul' => 'PhpParser\Node\Expr\AssignOp\Mul',166 'PHPParser_Node_Expr_AssignPlus' => 'PhpParser\Node\Expr\AssignOp\Plus',167 'PHPParser_Node_Expr_AssignShiftLeft' => 'PhpParser\Node\Expr\AssignOp\ShiftLeft',168 'PHPParser_Node_Expr_AssignShiftRight' => 'PhpParser\Node\Expr\AssignOp\ShiftRight',169 'PHPParser_Node_Expr_Cast' => 'PhpParser\Node\Expr\Cast',170 'PHPParser_Node_Expr_Cast_Array' => 'PhpParser\Node\Expr\Cast\Array_',171 'PHPParser_Node_Expr_Cast_Bool' => 'PhpParser\Node\Expr\Cast\Bool_',172 'PHPParser_Node_Expr_Cast_Double' => 'PhpParser\Node\Expr\Cast\Double',173 'PHPParser_Node_Expr_Cast_Int' => 'PhpParser\Node\Expr\Cast\Int_',174 'PHPParser_Node_Expr_Cast_Object' => 'PhpParser\Node\Expr\Cast\Object_',175 'PHPParser_Node_Expr_Cast_String' => 'PhpParser\Node\Expr\Cast\String_',176 'PHPParser_Node_Expr_Cast_Unset' => 'PhpParser\Node\Expr\Cast\Unset_',177 'PHPParser_Node_Expr_BitwiseAnd' => 'PhpParser\Node\Expr\BinaryOp\BitwiseAnd',178 'PHPParser_Node_Expr_BitwiseOr' => 'PhpParser\Node\Expr\BinaryOp\BitwiseOr',179 'PHPParser_Node_Expr_BitwiseXor' => 'PhpParser\Node\Expr\BinaryOp\BitwiseXor',180 'PHPParser_Node_Expr_BooleanAnd' => 'PhpParser\Node\Expr\BinaryOp\BooleanAnd',181 'PHPParser_Node_Expr_BooleanOr' => 'PhpParser\Node\Expr\BinaryOp\BooleanOr',182 'PHPParser_Node_Expr_Concat' => 'PhpParser\Node\Expr\BinaryOp\Concat',183 'PHPParser_Node_Expr_Div' => 'PhpParser\Node\Expr\BinaryOp\Div',184 'PHPParser_Node_Expr_Equal' => 'PhpParser\Node\Expr\BinaryOp\Equal',185 'PHPParser_Node_Expr_Greater' => 'PhpParser\Node\Expr\BinaryOp\Greater',186 'PHPParser_Node_Expr_GreaterOrEqual' => 'PhpParser\Node\Expr\BinaryOp\GreaterOrEqual',187 'PHPParser_Node_Expr_Identical' => 'PhpParser\Node\Expr\BinaryOp\Identical',188 'PHPParser_Node_Expr_LogicalAnd' => 'PhpParser\Node\Expr\BinaryOp\LogicalAnd',189 'PHPParser_Node_Expr_LogicalOr' => 'PhpParser\Node\Expr\BinaryOp\LogicalOr',190 'PHPParser_Node_Expr_LogicalXor' => 'PhpParser\Node\Expr\BinaryOp\LogicalXor',191 'PHPParser_Node_Expr_Minus' => 'PhpParser\Node\Expr\BinaryOp\Minus',192 'PHPParser_Node_Expr_Mod' => 'PhpParser\Node\Expr\BinaryOp\Mod',193 'PHPParser_Node_Expr_Mul' => 'PhpParser\Node\Expr\BinaryOp\Mul',194 'PHPParser_Node_Expr_NotEqual' => 'PhpParser\Node\Expr\BinaryOp\NotEqual',195 'PHPParser_Node_Expr_NotIdentical' => 'PhpParser\Node\Expr\BinaryOp\NotIdentical',196 'PHPParser_Node_Expr_Plus' => 'PhpParser\Node\Expr\BinaryOp\Plus',197 'PHPParser_Node_Expr_ShiftLeft' => 'PhpParser\Node\Expr\BinaryOp\ShiftLeft',198 'PHPParser_Node_Expr_ShiftRight' => 'PhpParser\Node\Expr\BinaryOp\ShiftRight',199 'PHPParser_Node_Expr_Smaller' => 'PhpParser\Node\Expr\BinaryOp\Smaller',200 'PHPParser_Node_Expr_SmallerOrEqual' => 'PhpParser\Node\Expr\BinaryOp\SmallerOrEqual',201 'PHPParser_Node_Expr_Array' => 'PhpParser\Node\Expr\Array_',202 'PHPParser_Node_Expr_ArrayDimFetch' => 'PhpParser\Node\Expr\ArrayDimFetch',203 'PHPParser_Node_Expr_ArrayItem' => 'PhpParser\Node\Expr\ArrayItem',204 'PHPParser_Node_Expr_Assign' => 'PhpParser\Node\Expr\Assign',205 'PHPParser_Node_Expr_AssignRef' => 'PhpParser\Node\Expr\AssignRef',206 'PHPParser_Node_Expr_BitwiseNot' => 'PhpParser\Node\Expr\BitwiseNot',207 'PHPParser_Node_Expr_BooleanNot' => 'PhpParser\Node\Expr\BooleanNot',208 'PHPParser_Node_Expr_ClassConstFetch' => 'PhpParser\Node\Expr\ClassConstFetch',209 'PHPParser_Node_Expr_Clone' => 'PhpParser\Node\Expr\Clone_',210 'PHPParser_Node_Expr_Closure' => 'PhpParser\Node\Expr\Closure',211 'PHPParser_Node_Expr_ClosureUse' => 'PhpParser\Node\Expr\ClosureUse',212 'PHPParser_Node_Expr_ConstFetch' => 'PhpParser\Node\Expr\ConstFetch',213 'PHPParser_Node_Expr_Empty' => 'PhpParser\Node\Expr\Empty_',214 'PHPParser_Node_Expr_ErrorSuppress' => 'PhpParser\Node\Expr\ErrorSuppress',215 'PHPParser_Node_Expr_Eval' => 'PhpParser\Node\Expr\Eval_',216 'PHPParser_Node_Expr_Exit' => 'PhpParser\Node\Expr\Exit_',217 'PHPParser_Node_Expr_FuncCall' => 'PhpParser\Node\Expr\FuncCall',218 'PHPParser_Node_Expr_Include' => 'PhpParser\Node\Expr\Include_',219 'PHPParser_Node_Expr_Instanceof' => 'PhpParser\Node\Expr\Instanceof_',220 'PHPParser_Node_Expr_Isset' => 'PhpParser\Node\Expr\Isset_',221 'PHPParser_Node_Expr_List' => 'PhpParser\Node\Expr\List_',222 'PHPParser_Node_Expr_MethodCall' => 'PhpParser\Node\Expr\MethodCall',223 'PHPParser_Node_Expr_New' => 'PhpParser\Node\Expr\New_',224 'PHPParser_Node_Expr_PostDec' => 'PhpParser\Node\Expr\PostDec',225 'PHPParser_Node_Expr_PostInc' => 'PhpParser\Node\Expr\PostInc',226 'PHPParser_Node_Expr_PreDec' => 'PhpParser\Node\Expr\PreDec',227 'PHPParser_Node_Expr_PreInc' => 'PhpParser\Node\Expr\PreInc',228 'PHPParser_Node_Expr_Print' => 'PhpParser\Node\Expr\Print_',229 'PHPParser_Node_Expr_PropertyFetch' => 'PhpParser\Node\Expr\PropertyFetch',230 'PHPParser_Node_Expr_ShellExec' => 'PhpParser\Node\Expr\ShellExec',231 'PHPParser_Node_Expr_StaticCall' => 'PhpParser\Node\Expr\StaticCall',232 'PHPParser_Node_Expr_StaticPropertyFetch' => 'PhpParser\Node\Expr\StaticPropertyFetch',233 'PHPParser_Node_Expr_Ternary' => 'PhpParser\Node\Expr\Ternary',234 'PHPParser_Node_Expr_UnaryMinus' => 'PhpParser\Node\Expr\UnaryMinus',235 'PHPParser_Node_Expr_UnaryPlus' => 'PhpParser\Node\Expr\UnaryPlus',236 'PHPParser_Node_Expr_Variable' => 'PhpParser\Node\Expr\Variable',237 'PHPParser_Node_Expr_Yield' => 'PhpParser\Node\Expr\Yield_',238 'PHPParser_Node_Scalar_ClassConst' => 'PhpParser\Node\Scalar\MagicConst\Class_',239 'PHPParser_Node_Scalar_DirConst' => 'PhpParser\Node\Scalar\MagicConst\Dir',240 'PHPParser_Node_Scalar_FileConst' => 'PhpParser\Node\Scalar\MagicConst\File',241 'PHPParser_Node_Scalar_FuncConst' => 'PhpParser\Node\Scalar\MagicConst\Function_',242 'PHPParser_Node_Scalar_LineConst' => 'PhpParser\Node\Scalar\MagicConst\Line',243 'PHPParser_Node_Scalar_MethodConst' => 'PhpParser\Node\Scalar\MagicConst\Method',244 'PHPParser_Node_Scalar_NSConst' => 'PhpParser\Node\Scalar\MagicConst\Namespace_',245 'PHPParser_Node_Scalar_TraitConst' => 'PhpParser\Node\Scalar\MagicConst\Trait_',246 'PHPParser_Node_Scalar_DNumber' => 'PhpParser\Node\Scalar\DNumber',247 'PHPParser_Node_Scalar_Encapsed' => 'PhpParser\Node\Scalar\Encapsed',248 'PHPParser_Node_Scalar_LNumber' => 'PhpParser\Node\Scalar\LNumber',249 'PHPParser_Node_Scalar_String' => 'PhpParser\Node\Scalar\String_',250 );251}252class_alias('PhpParser\Autoloader', 'PHPParser_Autoloader');...
xml_test.php
Source:xml_test.php
2// $Id: xml_test.php 1787 2008-04-26 20:35:39Z pp11 $3require_once(dirname(__FILE__) . '/../autorun.php');4require_once(dirname(__FILE__) . '/../xml.php');5Mock::generate('SimpleScorer');6if (! function_exists('xml_parser_create')) {7 SimpleTest::ignore('TestOfXmlStructureParsing');8 SimpleTest::ignore('TestOfXmlResultsParsing');9}10class TestOfNestingTags extends UnitTestCase {11 function testGroupSize() {12 $nesting = new NestingGroupTag(array('SIZE' => 2));13 $this->assertEqual($nesting->getSize(), 2);14 }15}16class TestOfXmlStructureParsing extends UnitTestCase {17 function testValidXml() {18 $listener = new MockSimpleScorer();19 $listener->expectNever('paintGroupStart');20 $listener->expectNever('paintGroupEnd');21 $listener->expectNever('paintCaseStart');22 $listener->expectNever('paintCaseEnd');23 $parser = new SimpleTestXmlParser($listener);24 $this->assertTrue($parser->parse("<?xml version=\"1.0\"?>\n"));25 $this->assertTrue($parser->parse("<run>\n"));26 $this->assertTrue($parser->parse("</run>\n"));27 }28 function testEmptyGroup() {29 $listener = new MockSimpleScorer();30 $listener->expectOnce('paintGroupStart', array('a_group', 7));31 $listener->expectOnce('paintGroupEnd', array('a_group'));32 $parser = new SimpleTestXmlParser($listener);33 $parser->parse("<?xml version=\"1.0\"?>\n");34 $parser->parse("<run>\n");35 $this->assertTrue($parser->parse("<group size=\"7\">\n"));36 $this->assertTrue($parser->parse("<name>a_group</name>\n"));37 $this->assertTrue($parser->parse("</group>\n"));38 $parser->parse("</run>\n");39 }40 function testEmptyCase() {41 $listener = new MockSimpleScorer();42 $listener->expectOnce('paintCaseStart', array('a_case'));43 $listener->expectOnce('paintCaseEnd', array('a_case'));44 $parser = new SimpleTestXmlParser($listener);45 $parser->parse("<?xml version=\"1.0\"?>\n");46 $parser->parse("<run>\n");47 $this->assertTrue($parser->parse("<case>\n"));48 $this->assertTrue($parser->parse("<name>a_case</name>\n"));49 $this->assertTrue($parser->parse("</case>\n"));50 $parser->parse("</run>\n");51 }52 function testEmptyMethod() {53 $listener = new MockSimpleScorer();54 $listener->expectOnce('paintCaseStart', array('a_case'));55 $listener->expectOnce('paintCaseEnd', array('a_case'));56 $listener->expectOnce('paintMethodStart', array('a_method'));57 $listener->expectOnce('paintMethodEnd', array('a_method'));58 $parser = new SimpleTestXmlParser($listener);59 $parser->parse("<?xml version=\"1.0\"?>\n");60 $parser->parse("<run>\n");61 $parser->parse("<case>\n");62 $parser->parse("<name>a_case</name>\n");63 $this->assertTrue($parser->parse("<test>\n"));64 $this->assertTrue($parser->parse("<name>a_method</name>\n"));65 $this->assertTrue($parser->parse("</test>\n"));66 $parser->parse("</case>\n");67 $parser->parse("</run>\n");68 }69 function testNestedGroup() {70 $listener = new MockSimpleScorer();71 $listener->expectAt(0, 'paintGroupStart', array('a_group', 7));72 $listener->expectAt(1, 'paintGroupStart', array('b_group', 3));73 $listener->expectCallCount('paintGroupStart', 2);74 $listener->expectAt(0, 'paintGroupEnd', array('b_group'));75 $listener->expectAt(1, 'paintGroupEnd', array('a_group'));76 $listener->expectCallCount('paintGroupEnd', 2);77 $parser = new SimpleTestXmlParser($listener);78 $parser->parse("<?xml version=\"1.0\"?>\n");79 $parser->parse("<run>\n");80 $this->assertTrue($parser->parse("<group size=\"7\">\n"));81 $this->assertTrue($parser->parse("<name>a_group</name>\n"));82 $this->assertTrue($parser->parse("<group size=\"3\">\n"));83 $this->assertTrue($parser->parse("<name>b_group</name>\n"));84 $this->assertTrue($parser->parse("</group>\n"));85 $this->assertTrue($parser->parse("</group>\n"));86 $parser->parse("</run>\n");87 }88}89class AnyOldSignal {90 public $stuff = true;91}92class TestOfXmlResultsParsing extends UnitTestCase {93 function sendValidStart(&$parser) {94 $parser->parse("<?xml version=\"1.0\"?>\n");95 $parser->parse("<run>\n");96 $parser->parse("<case>\n");97 $parser->parse("<name>a_case</name>\n");98 $parser->parse("<test>\n");99 $parser->parse("<name>a_method</name>\n");100 }101 function sendValidEnd(&$parser) {102 $parser->parse("</test>\n");103 $parser->parse("</case>\n");104 $parser->parse("</run>\n");105 }106 function testPass() {107 $listener = new MockSimpleScorer();108 $listener->expectOnce('paintPass', array('a_message'));109 $parser = new SimpleTestXmlParser($listener);110 $this->sendValidStart($parser);111 $this->assertTrue($parser->parse("<pass>a_message</pass>\n"));112 $this->sendValidEnd($parser);113 }114 function testFail() {115 $listener = new MockSimpleScorer();116 $listener->expectOnce('paintFail', array('a_message'));117 $parser = new SimpleTestXmlParser($listener);118 $this->sendValidStart($parser);119 $this->assertTrue($parser->parse("<fail>a_message</fail>\n"));120 $this->sendValidEnd($parser);121 }122 function testException() {123 $listener = new MockSimpleScorer();124 $listener->expectOnce('paintError', array('a_message'));125 $parser = new SimpleTestXmlParser($listener);126 $this->sendValidStart($parser);127 $this->assertTrue($parser->parse("<exception>a_message</exception>\n"));128 $this->sendValidEnd($parser);129 }130 function testSkip() {131 $listener = new MockSimpleScorer();132 $listener->expectOnce('paintSkip', array('a_message'));133 $parser = new SimpleTestXmlParser($listener);134 $this->sendValidStart($parser);135 $this->assertTrue($parser->parse("<skip>a_message</skip>\n"));136 $this->sendValidEnd($parser);137 }138 function testSignal() {139 $signal = new AnyOldSignal();140 $signal->stuff = "Hello";141 $listener = new MockSimpleScorer();142 $listener->expectOnce('paintSignal', array('a_signal', $signal));143 $parser = new SimpleTestXmlParser($listener);144 $this->sendValidStart($parser);145 $this->assertTrue($parser->parse(146 "<signal type=\"a_signal\"><![CDATA[" .147 serialize($signal) . "]]></signal>\n"));148 $this->sendValidEnd($parser);149 }150 function testMessage() {151 $listener = new MockSimpleScorer();152 $listener->expectOnce('paintMessage', array('a_message'));153 $parser = new SimpleTestXmlParser($listener);154 $this->sendValidStart($parser);155 $this->assertTrue($parser->parse("<message>a_message</message>\n"));156 $this->sendValidEnd($parser);157 }158 function testFormattedMessage() {159 $listener = new MockSimpleScorer();160 $listener->expectOnce('paintFormattedMessage', array("\na\tmessage\n"));161 $parser = new SimpleTestXmlParser($listener);162 $this->sendValidStart($parser);163 $this->assertTrue($parser->parse("<formatted><![CDATA[\na\tmessage\n]]></formatted>\n"));164 $this->sendValidEnd($parser);165 }166}167?>...
combinator.php
Source:combinator.php
...5 use \verfriemelt\pp\Parser\Parser;6 use \verfriemelt\pp\Parser\ParserInput;7 use \verfriemelt\pp\Parser\ParserInputInterface;8 use \verfriemelt\pp\Parser\ParserState;9 function choice( Parser ... $parsers ): Parser {10 return new Parser( 'choice', static function ( ParserInputInterface $input, ParserState $state ) use ( &$parsers ): ParserState {11 foreach ( $parsers as $parser ) {12 $newState = $parser->run( $input, $state );13 if ( !$newState->isError() && $newState->getIndex() > $state->getIndex() ) {14 return $newState;15 }16 }17 return $state->error( "chould not match with any parser at position {$state->getIndex()}" );18 } );19 }20 function sequenceOf( Parser ... $parsers ): Parser {21 return new Parser( 'choice', static function ( ParserInputInterface $input, ParserState $state ) use ( &$parsers ): ParserState {22 if ( $state->isError() ) {23 return $state;24 }25 $currentState = $state;26 $results = [];27 foreach ( $parsers as $parser ) {28 $currentState = $parser->run( $input, $currentState );29 $results[] = $currentState->getResult();30 }31 return $currentState->result( $results );32 } );33 }34 function many( Parser $parser ): Parser {35 return new Parser( 'many', static function ( ParserInputInterface $input, ParserState $currentState ) use ( &$parser ): ParserState {36 $results = [];37 $isDone = false;38 while ( !$isDone ) {39 $nextState = $parser->run( $input, $currentState );40 if ( !$nextState->isError() && $nextState->getIndex() > $currentState->getIndex() ) {41 $results[] = $nextState->getResult();42 $currentState = $nextState;43 } else {44 $isDone = true;45 }46 }47 return $currentState->result( $results );48 } );49 }50 function manyOne( Parser $parser ): Parser {51 return new Parser( 'many', static function ( ParserInputInterface $input, ParserState $currentState ) use ( &$parser ): ParserState {52 $results = [];53 $isDone = false;54 while ( !$isDone ) {55 $nextState = $parser->run( $input, $currentState );56 if ( !$nextState->isError() && $nextState->getIndex() > $currentState->getIndex() ) {57 $results[] = $nextState->getResult();58 $currentState = $nextState;59 } else {60 $isDone = true;61 }62 }63 if ( count( $results ) === 0 ) {64 return $currentState->error( 'must at least match one parser at index ' . $currentState->getIndex() );65 }66 return $currentState->result( $results );67 } );68 }69 function seperatedBy( Parser $seperator ): Closure {70 return static fn( Parser $value ) => new Parser( 'seperatered', static function ( ParserInputInterface $input, ParserState $state ) use ( &$value, &$seperator ): ParserState {71 $results = [];72 $currentState = $state;73 while ( true ) {74 $nextState = $value->run( $input, $currentState );75 if ( !$nextState->isError() && $nextState->getIndex() > $currentState->getIndex() ) {76 $results[] = $nextState->getResult();77 $currentState = $nextState;78 } else {79 break;80 }81 $nextState = $seperator->run( $input, $currentState );82 if ( !$nextState->isError() && $nextState->getIndex() > $currentState->getIndex() ) {83 $currentState = $nextState;84 } else {85 break;86 }87 }88 return $currentState->result( $results );89 } );90 }91 function between( Parser $left, Parser $right ): Closure {92 return static fn( Parser $between ) => sequenceOf(93 $left,94 $between,95 $right,96 )->map( fn( $r ) => $r[1] );97 }98 function lazy( \Closure $lazy ): Parser {99 return new Parser( 'lazy', static function ( ParserInputInterface $input, ParserState $state ) use ( &$lazy ): ParserState {100 return $lazy()->run( $input, $state );101 } );102 }103 function succeed( mixed $value ): Parser {104 return new Parser( 'succeed', static fn( ParserInput $input, ParserState $state ): ParserState => $state->result( $value ) );105 }106 function fail( string $msg ): Parser {107 return new Parser( 'succeed', static fn( ParserInput $input, ParserState $state ): ParserState => $state->error( $msg ) );108 }109 function contextual( \Closure $generator ): Closure {110 return static fn() => succeed( null )->chain( static function () use ( $generator ) {111 $iterator = null;112 $step = static function ( $nextValue = null ) use ( &$step, &$iterator, &$generator ) {113 if ( $iterator === null ) {114 $iterator = $generator();115 $parser = $iterator->current();116 } else {117 $parser = $iterator->send( $nextValue );118 }119 if ( !$iterator->valid() ) {120 return succeed( $nextValue );121 }122 return $parser->chain( $step );123 };124 return $step();125 } );126 }127 function optional( Parser $parser ): Parser {128 $opt = new Parser( 'optional', static function ( ParserInputInterface $input, ParserState $currentState ) use ( &$parser ): ParserState {129 $nextState = $parser->run( $input, $currentState );130 if ( !$nextState->isError() ) {131 return $nextState;132 }133 return $currentState;134 } );135 return succeed( null )->chain( contextual( function () use ( $opt ) {136 return succeed( yield $opt );137 } ) );138 }139 function not( Parser $parser ): Parser {140 return new Parser( 'not', static function ( ParserInputInterface $input, ParserState $currentState ) use ( &$parser ): ParserState {141 $nextState = $parser->run( $input, $currentState );142 if ( $nextState->isError() ) {143 return $currentState;144 }145 return $currentState->error( 'should have not matched parser' );146 } );147 }...
TokenParserBroker.php
Source:TokenParserBroker.php
...8 * For the full copyright and license information, please view the LICENSE9 * file that was distributed with this source code.10 */11/**12 * Default implementation of a token parser broker.13 *14 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>15 * @deprecated since 1.12 (to be removed in 2.0)16 */17class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface18{19 protected $parser;20 protected $parsers = array();21 protected $brokers = array();22 /**23 * Constructor.24 *25 * @param array|Traversable $parsers A Traversable of Twig_TokenParserInterface instances26 * @param array|Traversable $brokers A Traversable of Twig_TokenParserBrokerInterface instances27 */28 public function __construct($parsers = array(), $brokers = array())29 {30 foreach ($parsers as $parser) {31 if (!$parser instanceof Twig_TokenParserInterface) {32 throw new LogicException('$parsers must a an array of Twig_TokenParserInterface');33 }34 $this->parsers[$parser->getTag()] = $parser;35 }36 foreach ($brokers as $broker) {37 if (!$broker instanceof Twig_TokenParserBrokerInterface) {38 throw new LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface');39 }40 $this->brokers[] = $broker;41 }42 }43 /**44 * Adds a TokenParser.45 *46 * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance47 */48 public function addTokenParser(Twig_TokenParserInterface $parser)49 {50 $this->parsers[$parser->getTag()] = $parser;51 }52 /**53 * Removes a TokenParser.54 *55 * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance56 */57 public function removeTokenParser(Twig_TokenParserInterface $parser)58 {59 $name = $parser->getTag();60 if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) {61 unset($this->parsers[$name]);62 }63 }64 /**65 * Adds a TokenParserBroker.66 *67 * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance68 */69 public function addTokenParserBroker(Twig_TokenParserBroker $broker)70 {71 $this->brokers[] = $broker;72 }73 /**74 * Removes a TokenParserBroker.75 *76 * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance77 */78 public function removeTokenParserBroker(Twig_TokenParserBroker $broker)79 {80 if (false !== $pos = array_search($broker, $this->brokers)) {81 unset($this->brokers[$pos]);82 }83 }84 /**85 * Gets a suitable TokenParser for a tag.86 *87 * First looks in parsers, then in brokers.88 *89 * @param string $tag A tag name90 *91 * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found92 */93 public function getTokenParser($tag)94 {95 if (isset($this->parsers[$tag])) {96 return $this->parsers[$tag];97 }98 $broker = end($this->brokers);99 while (false !== $broker) {100 $parser = $broker->getTokenParser($tag);101 if (null !== $parser) {102 return $parser;103 }104 $broker = prev($this->brokers);105 }106 }107 public function getParsers()108 {109 return $this->parsers;110 }111 public function getParser()112 {113 return $this->parser;114 }115 public function setParser(Twig_ParserInterface $parser)116 {117 $this->parser = $parser;118 foreach ($this->parsers as $tokenParser) {119 $tokenParser->setParser($parser);120 }121 foreach ($this->brokers as $broker) {122 $broker->setParser($parser);123 }124 }125}...
parser
Using AI Code Generation
1use mageekguy\atoum\reports\realtime\cli;2use mageekguy\atoum\reports\realtime\cli\colorizer;3use mageekguy\atoum\reports\realtime\cli\colorizer\styles;4use mageekguy\atoum\reports\realtime\cli\colorizer\style;5use mageekguy\atoum\reports\realtime\cli\colorizer\styles\builder;6use mageekguy\atoum\reports\realtime\cli\colorizer\styles\builder\cli;7use mageekguy\atoum\reports\realtime\cli\colorizer\styles\builder\cli\colors;8$cliColorizer = new colorizer();9$cliColorizer->setStylesBuilder(new builder(new cli(new colors())));10$test->addReport(new cli());11$test->addReport($cliColorizer);12$test->run();13use mageekguy\atoum\reports\realtime\cli;14use mageekguy\atoum\reports\realtime\cli\colorizer;15use mageekguy\atoum\reports\realtime\cli\colorizer\styles;16use mageekguy\atoum\reports\realtime\cli\colorizer\style;17use mageekguy\atoum\reports\realtime\cli\colorizer\styles\builder;18use mageekguy\atoum\reports\realtime\cli\colorizer\styles\builder\cli;19use mageekguy\atoum\reports\realtime\cli\colorizer\styles\builder\cli\colors;20$cliColorizer = new colorizer();21$cliColorizer->setStylesBuilder(new builder(new cli(new colors())));22$test->addReport(new cli());23$test->addReport($cliColorizer);24$test->run();25use mageekguy\atoum\reports\realtime\cli;26use mageekguy\atoum\reports\realtime\cli\colorizer;
parser
Using AI Code Generation
1$parser = new atoum\atoum\scripts\runner\parser();2$parser->parse();3$parser = new atoum\atoum\scripts\runner\parser();4$parser->parse();5$parser = new atoum\atoum\scripts\runner\parser();6$parser->parse();7$parser = new atoum\atoum\scripts\runner\parser();8$parser->parse();9$parser = new atoum\atoum\scripts\runner\parser();10$parser->parse();11$parser = new atoum\atoum\scripts\runner\parser();12$parser->parse();13$parser = new atoum\atoum\scripts\runner\parser();14$parser->parse();15$parser = new atoum\atoum\scripts\runner\parser();16$parser->parse();17$parser = new atoum\atoum\scripts\runner\parser();18$parser->parse();19$parser = new atoum\atoum\scripts\runner\parser();20$parser->parse();21$parser = new atoum\atoum\scripts\runner\parser();22$parser->parse();23$parser = new atoum\atoum\scripts\runner\parser();24$parser->parse();
parser
Using AI Code Generation
1use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;2use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;3use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;4use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;5use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;6use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;7use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;8use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;9use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;10use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;11use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;12use mageekguy\atoum\report\fields\runner\tests\coverage\html\parser;
parser
Using AI Code Generation
1require_once 'atoum.php';2$parser = new atoum\parser();3$parser->parseFile('2.php');4$parser->parseFile('3.php');5$parser->parseFile('4.php');6$parser->parseFile('5.php');7$parser->parseFile('6.php');8$parser->parseFile('7.php');9$parser->parseFile('8.php');10$parser->parseFile('9.php');11$parser->parseFile('10.php');12$parser->parseFile('11.php');13$parser->parseFile('12.php');14$parser->parseFile('13.php');15$parser->parseFile('14.php');16$parser->parseFile('15.php');17$parser->parseFile('16.php');18$parser->parseFile('17.php');19$parser->parseFile('18.php');20$parser->parseFile('19.php');21$parser->parseFile('20.php');22$parser->parseFile('21.php');23$parser->parseFile('22.php');24$parser->parseFile('23.php');25$parser->parseFile('24.php');26$parser->parseFile('25.php');27$parser->parseFile('26.php');28$parser->parseFile('27.php');29$parser->parseFile('28.php');30$parser->parseFile('29.php');31$parser->parseFile('30.php');32$parser->parseFile('31.php');33$parser->parseFile('32.php');34$parser->parseFile('33.php');35$parser->parseFile('34.php');36$parser->parseFile('35.php');37$parser->parseFile('36.php');38$parser->parseFile('37.php');39$parser->parseFile('38.php');40$parser->parseFile('39.php');41$parser->parseFile('40.php');42$parser->parseFile('41.php');43$parser->parseFile('42.php');44$parser->parseFile('43.php');45$parser->parseFile('44.php');46$parser->parseFile('45.php');47$parser->parseFile('46.php');48$parser->parseFile('47.php');49$parser->parseFile('48.php');50$parser->parseFile('49.php');51$parser->parseFile('50.php');52$parser->parseFile('51.php');53$parser->parseFile('52.php');54$parser->parseFile('53.php');55$parser->parseFile('54.php');
parser
Using AI Code Generation
1$parser = new \mageekguy\atoum\report\fields\runner\coverage\html\parser();2$parser->addDirectory('/path/to/1');3$parser->addDirectory('/path/to/2');4$parser->parse('/path/to/file/to/parse.php');5$parser->generate('/path/to/destination/directory');6$parser = new \mageekguy\atoum\report\fields\runner\coverage\html\parser();7$parser->addDirectory('/path/to/1');8$parser->addDirectory('/path/to/2');9$parser->parse('/path/to/file/to/parse.php');10$parser->generate('/path/to/destination/directory');
parser
Using AI Code Generation
1require_once 'vendor/autoload.php';2require_once 'vendor/atoum/atoum/classes/mock/generator.php';3$parser = new \mock\atoum\atoum\mock\generator();4$parser->getMockController()->getTestedClassName = 'test';5$parser->getMockController()->getTestedClassNamespace = 'test';6$parser->getMockController()->getTestedClassCode = 'test';7$parser->getMockController()->getTestedClassIsAbstract = false;8$parser->getMockController()->getTestedClassParentClass = 'test';9$parser->getMockController()->getTestedClassInterfaces = 'test';10$parser->getMockController()->getTestedClassConstants = 'test';11$parser->getMockController()->getTestedClassMethods = 'test';12$parser->getMockController()->getTestedClassProperties = 'test';13$parser->getMockController()->getTestedClassTraits = 'test';14$parser->getMockController()->getTestedClassUseStatements = 'test';15$parser->getMockController()->getTestedClassIsFinal = false;16$parser->getMockController()->getTestedClassIsAnonymous = false;17$parser->getMockController()->getTestedClassIsTested = false;18$parser->getMockController()->getTestedClassIsMock = false;19$parser->getMockController()->getTestedClassIsInterface = false;20$parser->getMockController()->getTestedClassIsTrait = false;21$parser->getMockController()->getTestedClassIsAbstract = false;22$parser->getMockController()->getTestedClassIsFinal = false;23$parser->getMockController()->getTestedClassIsAnonymous = false;24$parser->getMockController()->getTestedClassIsTested = false;25$parser->getMockController()->getTestedClassIsMock = false;26$parser->getMockController()->getTestedClassIsInterface = false;27$parser->getMockController()->getTestedClassIsTrait = false;28$parser->getMockController()->getTestedClassIsAbstract = false;29$parser->getMockController()->getTestedClassIsFinal = false;30$parser->getMockController()->getTestedClassIsAnonymous = false;31$parser->getMockController()->getTestedClassIsTested = false;32$parser->getMockController()->getTestedClassIsMock = false;33$parser->getMockController()->getTestedClassIsInterface = false
parser
Using AI Code Generation
1require_once 'atoum.php';2$parser = new atoum\parser();3$parser->parseFile('1.php');4$parser->run();5require_once 'atoum.php';6$parser = new atoum\parser();7$parser->parseFile('2.php');8$parser->run();9require_once 'atoum.php';10$parser = new atoum\parser();11$parser->parseFile('3.php');12$parser->run();13require_once 'atoum.php';14$parser = new atoum\parser();15$parser->parseFile('4.php');16$parser->run();17require_once 'atoum.php';18$parser = new atoum\parser();19$parser->parseFile('5.php');20$parser->run();21require_once 'atoum.php';22$parser = new atoum\parser();23$parser->parseFile('6.php');24$parser->run();25require_once 'atoum.php';26$parser = new atoum\parser();27$parser->parseFile('7.php');28$parser->run();29require_once 'atoum.php';30$parser = new atoum\parser();31$parser->parseFile('8.php');32$parser->run();33require_once 'atoum.php';34$parser = new atoum\parser();35$parser->parseFile('9.php');36$parser->run();37require_once 'atoum.php';38$parser = new atoum\parser();39$parser->parseFile('10.php');40$parser->run();
parser
Using AI Code Generation
1require_once '/path/to/Atoum/Tests/Unit/Parser.php';2$parser = new Atoum\Parser();3$parser->parseFile('path/to/file/to/test.php');4require_once '/path/to/Atoum/Tests/Unit/Parser.php';5$parser = new Atoum\Parser();6$parser->parseFile('path/to/file/to/test.php');7require_once '/path/to/Atoum/Tests/Unit/Parser.php';8$parser = new Atoum\Parser();9$parser->parseFile('path/to/file/to/test.php');10require_once '/path/to/Atoum/Tests/Unit/Parser.php';11$parser = new Atoum\Parser();12$parser->parseFile('path/to/file/to/test.php');13require_once '/path/to/Atoum/Tests/Unit/Parser.php';14$parser = new Atoum\Parser();15$parser->parseFile('path/to/file/to/test.php');16require_once '/path/to/Atoum/Tests/Unit/Parser.php';17$parser = new Atoum\Parser();18$parser->parseFile('path/to/file/to/test.php');19require_once '/path/to/Atoum/Tests/Unit/Parser.php';20$parser = new Atoum\Parser();21$parser->parseFile('path/to/file/to/test.php');22require_once '/path/to/Atoum/Tests/Unit/Parser.php';23$parser = new Atoum\Parser();24$parser->parseFile('path/to/file/to/test.php');25require_once '/path/to/Atoum/Tests/Unit/Parser.php';26$parser = new Atoum\Parser();27$parser->parseFile('path
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Trigger Selenium automation tests on a cloud-based Grid of 3000+ real browsers and operating systems.
Test now for FreeGet 100 minutes of automation test minutes FREE!!